mx51 TVOUT分析

2023-05-16

1397 static int __init enable_tve_setup(char *options)
1398 {
1399     g_enable_tve = true;
1400 
1401     return 1;
1402 }
1403 __setup("tve", enable_tve_setup);

一般情况,freescale会推荐在kernel命令行参数中使能TVE, 这个函数就是处理kernel传入的参数

'init=/init androidboot.console=ttymxc0 di1_primary video=mxcdi1fb:YUV444, 720x576-i@50 tve'


1198 static int tve_probe(struct platform_device *pdev)

1199 {
1200     int ret, i, primary = 0;
1201     struct resource *res;
1202     struct tve_platform_data *plat_data = pdev->dev.platform_data;
1203     u32 conf_reg;
1204 
1205     if (g_enable_tve == false)
1206         return -EPERM;
1207 
1208     INIT_LIST_HEAD(&tve_modelist.list);
1209 
1210     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1211     if (res == NULL)
1212         return -ENOMEM;
1213 
1214     tve.pdev = pdev;
1215     tve.base = ioremap(res->start, res->end - res->start);
1216 
1217     tve.irq = platform_get_irq(pdev, 0);
1218     if (tve.irq < 0) {
1219         ret = tve.irq;
1220         goto err0;
1221     }
1222 
1223     ret = request_irq(tve.irq, tve_detect_handler, 0, pdev->name, pdev);
1224     if (ret < 0)
1225         goto err0;
1226 
1227     ret = device_create_file(&pdev->dev, &dev_attr_headphone);
1228     if (ret < 0)
1229         goto err1;
1230 
1231     for (i = 0; i < num_registered_fb; i++) {
1232         if (strcmp(registered_fb[i]->fix.id, "DISP3 BG - DI1") == 0) {
1233             tve_fbi = registered_fb[i];
1234             if (i == 0) {
1235                 pr_info("TVE as primary display\n");
1236                 primary = 1;
1237                 acquire_console_sem();
1238                 fb_blank(tve_fbi, FB_BLANK_POWERDOWN);
1239                 release_console_sem();
1240             }
1241             break;
1242         }
1243     }

1215 映射TVE寄存器地址到,结果保存到tve.base中

1217~1225 注册Cable Detect handler

1227 创建headphone属性文件,可以通过cat /sys/devices/platform/tve.0/headphone查看当前 cable 状态。

1231~1243 如果在kernel cmdline中指定了di1_primary,那么registered_fb[0] 的id就是"DISP3 BG - DI1",此时关闭fb_blank

1257 ~ 1266 获取di1和TVE的时钟

1267 ~ 1269 设置TVE的时钟rate,设置tve_clk1为di1_clk的父亲,这样启动di1就会为tve时钟上电; 

1269 使能tve clk,这样才能操作tve的寄存器。

1271 ~ 1278 获取tve 版本;根据tve 的版本,来选择要操作的寄存器集合,

1292 ~ 1306 video_modes PAL, NTSC, 720P 是rev1和rev2都支持的video mode,rev2支持其他集中模式,XGA和SXGA仅在53上支持。

1309 初始化一个动作队列,这个工作队列是用来处理cable detect

1310 ~ 1313 设置cable detect register

1325 已经操作完TVE的寄存器,可以关闭clk了

1327 注册一个notifier callback,这样在fb event事件发生时就可以调用这个callback

1334  TVE是primary frame buffer,所以要显示logo

1343 不知道为什么要设置为 var.yres * 3 以后回来再看

1348~1356 关闭frame buffer再打开frame buffer


1179 static int _tve_get_revision(void)
1180 {
1181     u32 conf_reg;
1182     u32 rev = 0;
1183 
1184     /* find out TVE rev based on the base addr default value
1185      * can be used at the init/probe ONLY */
1186     conf_reg = __raw_readl(tve.base);
1187     switch (conf_reg) {
1188     case 0x00842000:
1189         rev = 1;
1190         break;
1191     case 0x00100000:
1192         rev = 2;
1193         break;
1194     }
1195     return rev;
1196 }

通过读取0xBASE_0000寄存器的初始缺省值来获取TVE的版本号


1147 static ssize_t show_headphone(struct device *dev,
1148         struct device_attribute *attr, char *buf)
1149 {
1150     int detect;
1151 
1152     if (!enabled) {
1153         strcpy(buf, "tve power off\n");
1154         return strlen(buf);
1155     }
1156 
1157     detect = tve_update_detect_status();
1158 
1159     if (detect == 0)
1160         strcpy(buf, "none\n");
1161     else if (detect == 1)
1162         strcpy(buf, "cvbs\n");
1163     else if (detect == 2)
1164         strcpy(buf, "headset\n");
1165     else if (detect == 3)
1166         strcpy(buf, "component\n");
1167     else
1168         strcpy(buf, "svideo\n");
1169 
1170     return strlen(buf);
1171 }
这个函数是一个sys接口的show函数,用来显示当前cable的插入状态,cat /sys/devices/platform/tve.0/headphone将显示相应状态

1157是真正的cable检测函数


 632 static int tve_update_detect_status(void)
 633 {
 634     int old_detect = tve.detect;
 635     u32 stat_lm, stat_sm, stat;
 636     u32 int_ctl;
 637     u32 cd_cont_reg;
 638     u32 timeout = 40;
 639     unsigned long lock_flags;
 640 
 641     spin_lock_irqsave(&tve_lock, lock_flags);
 642 
 643     if (!enabled) {
 644         pr_warning("Warning: update tve status while it disabled!\n");
 645         tve.detect = 0;
 646         goto done;
 647     }
 648 
 649     int_ctl = __raw_readl(tve.base + tve_regs->tve_int_cont_reg);
 650     cd_cont_reg = __raw_readl(tve.base + tve_regs->tve_cd_cont_reg);
 651 
 652     if ((cd_cont_reg & 0x1) == 0) {
 653         pr_warning("Warning: pls enable TVE CD first!\n");
 654         goto done;
 655     }
 656 
 657     stat = __raw_readl(tve.base + tve_regs->tve_stat_reg);
 658     while (((stat & CD_MON_END_INT) == 0) && (timeout > 0)) {
 659         spin_unlock_irqrestore(&tve_lock, lock_flags);
 660         msleep(2);
 661         spin_lock_irqsave(&tve_lock, lock_flags);
 662         timeout -= 2;
 663         if (!enabled) {
 664             pr_warning("Warning: update tve status while it disabled!\n");
 665             tve.detect = 0;
 666             goto done;
 667         } else
 668             stat = __raw_readl(tve.base + tve_regs->tve_stat_reg);
 669     }
 670     if (((stat & CD_MON_END_INT) == 0) && (timeout <= 0)) {
 671         pr_warning("Warning: get detect result without CD_MON_END_INT!\n");
 672         goto done;
 673     }
 674 
 675     stat = stat >> tve_reg_fields->cd_ch_stat_offset;
 676     stat_lm = stat & (CD_CH_0_LM_ST | CD_CH_1_LM_ST | CD_CH_2_LM_ST);
 677     if ((stat_lm == (CD_CH_0_LM_ST | CD_CH_1_LM_ST | CD_CH_2_LM_ST)) &&
 678         ((stat & (CD_CH_0_SM_ST | CD_CH_1_SM_ST | CD_CH_2_SM_ST)) == 0)
 679         ) {
 680             tve.detect = 3;
 681             tve.output_mode = YPBPR;
 682     } else if ((stat_lm == (CD_CH_0_LM_ST | CD_CH_1_LM_ST)) &&
 683         ((stat & (CD_CH_0_SM_ST | CD_CH_1_SM_ST)) == 0)) {
 684             tve.detect = 4;
 685             tve.output_mode = SVIDEO;
 686     } else if (stat_lm == CD_CH_0_LM_ST) {
 687         stat_sm = stat & CD_CH_0_SM_ST;
 688         if (stat_sm != 0) {
 689             /* headset */
 690             tve.detect = 2;
 691             tve.output_mode = TV_OFF;
 692         } else {
 693             tve.detect = 1;
 694             tve.output_mode = CVBS0;
 695         }
 696     } else if (stat_lm == CD_CH_2_LM_ST) {
 697         stat_sm = stat & CD_CH_2_SM_ST;
 698         if (stat_sm != 0) {
 699             /* headset */
 700             tve.detect = 2;
 701             tve.output_mode = TV_OFF;
 702         } else {
 703             tve.detect = 1;
 704             tve.output_mode = CVBS2;
 705         }
 706     } else {
 707         /* none */
 708         tve.detect = 0;
 709         tve.output_mode = TV_OFF;
 710     }
 711 
 712     tve_set_tvout_mode(tve.output_mode);
 713 
 714     /* clear interrupt */
 715     __raw_writel(CD_MON_END_INT | CD_LM_INT | CD_SM_INT,
 716             tve.base + tve_regs->tve_stat_reg);
 717 
 718     __raw_writel(int_ctl | CD_SM_INT | CD_LM_INT,
 719             tve.base + tve_regs->tve_int_cont_reg);
 720 
 721     if (old_detect != tve.detect)
 722         sysfs_notify(&tve.pdev->dev.kobj, NULL, "headphone");
 723 
 724     dev_dbg(&tve.pdev->dev, "detect = %d mode = %d\n",
 725             tve.detect, tve.output_mode);
 726 done:
 727     spin_unlock_irqrestore(&tve_lock, lock_flags);
 728     return tve.detect;
 729 }

643 ~ 647 TVE当前是disable的,所以不会做检测,直接返回tve.detect=0

650 ~655 应该使能CD_EN

657 ~ 669 每2ms检测一次tve_stat_reg,直到CD_MON_END_INT发生或者timeout

670 ~ 673 无CD_MON_END_INT中断发生,返回

675~710 根据tve_state_reg中的CD_CH_x_LM_ST和CD_CH_x_SM_ST来决定cable的插入状态

712 tve_set_tvout_mode是根据当前的cable 状态来调整tve out 模式

715 ~ 717 清空tve_stat_reg的cable detect状态位,写1清空

718 ~ 719 使能CD_SM_INT和CD_LM_INT,检测 cable的插拔

721 ~ 722 上报headphone事件给poll这个headphone文件描述符的进程


 913 int tve_fb_event(struct notifier_block *nb, unsigned long val, void *v)
 914 {
 915     struct fb_event *event = v;
 916     struct fb_info *fbi = event->info;
 917 
 918     if (strcmp(fbi->fix.id, "DISP3 BG - DI1"))
 919         return 0;
 920 
 921     switch (val) {
 922     case FB_EVENT_FB_REGISTERED:
 923         pr_debug("fb registered event\n");
 924         if (tve_fbi != NULL)
 925             break;
 926 
 927         tve_fbi = fbi;
 928         fb_add_videomode(&video_modes[0], &tve_modelist.list);
 929         fb_add_videomode(&video_modes[1], &tve_modelist.list);
 930         fb_add_videomode(&video_modes[2], &tve_modelist.list);
 931         if (tve.revision == 2) {
 932             fb_add_videomode(&video_modes[3], &tve_modelist.list);
 933             fb_add_videomode(&video_modes[4], &tve_modelist.list);
 934             fb_add_videomode(&video_modes[5], &tve_modelist.list);
 935             fb_add_videomode(&video_modes[6], &tve_modelist.list);
 936             fb_add_videomode(&video_modes[7], &tve_modelist.list);
 937             fb_add_videomode(&video_modes[8], &tve_modelist.list);
 938             if (cpu_is_mx53()) {
 939                 fb_add_videomode(&video_modes[9], &tve_modelist.list);
 940                 fb_add_videomode(&video_modes[10], &tve_modelist.list);
 941             }
 942         }
 943         break;
 944     case FB_EVENT_MODE_CHANGE:
 945     {
 946         if (tve_fbi != fbi)
 947             break;
 948 
 949         fbi->mode = (struct fb_videomode *)fb_match_mode(&tve_fbi->var,
 950                 &tve_modelist.list);
 951 
 952         if (!fbi->mode) {
 953             pr_warning("TVE: can not find mode for xres=%d, yres=%d\n",
 954                     fbi->var.xres, fbi->var.yres);
 955             tve_disable();
 956             tve.cur_mode = TVOUT_FMT_OFF;
 957             return 0;
 958         }
 959 
 960         pr_debug("TVE: fb mode change event: xres=%d, yres=%d\n",
 961              fbi->mode->xres, fbi->mode->yres);
 962 
 963         if (fb_mode_is_equal(fbi->mode, &video_modes[0])) {
 964             tve_set_di_fmt(fbi, IPU_PIX_FMT_YUV444);
 965             tve_disable();
 966             tve_setup(TVOUT_FMT_NTSC);
 967             if (tve.blank == FB_BLANK_UNBLANK)
 968                 tve_enable();
 969         } else if (fb_mode_is_equal(fbi->mode, &video_modes[1])) {
 970             tve_set_di_fmt(fbi, IPU_PIX_FMT_YUV444);
 971             tve_disable();
 972             tve_setup(TVOUT_FMT_PAL);
 973             if (tve.blank == FB_BLANK_UNBLANK)
 974                 tve_enable();
 975         } else if (fb_mode_is_equal(fbi->mode, &video_modes[2])) {
 976             tve_set_di_fmt(fbi, IPU_PIX_FMT_YUV444);
 977             tve_disable();
 978             tve_setup(TVOUT_FMT_720P60);
 979             if (tve.blank == FB_BLANK_UNBLANK)
 980                 tve_enable();
 981         } else if (fb_mode_is_equal(fbi->mode, &video_modes[3])) {
 982             tve_set_di_fmt(fbi, IPU_PIX_FMT_YUV444);
 983             tve_disable();
 984             tve_setup(TVOUT_FMT_720P30);
 985             if (tve.blank == FB_BLANK_UNBLANK)
 986                 tve_enable();
 987         } else if (fb_mode_is_equal(fbi->mode, &video_modes[4])) {
 988             tve_set_di_fmt(fbi, IPU_PIX_FMT_YUV444);
 989             tve_disable();
 990             tve_setup(TVOUT_FMT_1080I60);
 991             if (tve.blank == FB_BLANK_UNBLANK)
 992                 tve_enable();
 993         } else if (fb_mode_is_equal(fbi->mode, &video_modes[5])) {
 994             tve_set_di_fmt(fbi, IPU_PIX_FMT_YUV444);
 995             tve_disable();
 996             tve_setup(TVOUT_FMT_1080I50);
 997             if (tve.blank == FB_BLANK_UNBLANK)
 998                 tve_enable();
 999         } else if (fb_mode_is_equal(fbi->mode, &video_modes[6])) {
1000             tve_set_di_fmt(fbi, IPU_PIX_FMT_YUV444);
1001             tve_disable();
1002             tve_setup(TVOUT_FMT_1080P30);
1003             if (tve.blank == FB_BLANK_UNBLANK)
1004                 tve_enable();
1005         } else if (fb_mode_is_equal(fbi->mode, &video_modes[7])) {
1006             tve_set_di_fmt(fbi, IPU_PIX_FMT_YUV444);
1007             tve_disable();
1008             tve_setup(TVOUT_FMT_1080P25);
1009             if (tve.blank == FB_BLANK_UNBLANK)
1010                 tve_enable();
1011         } else if (fb_mode_is_equal(fbi->mode, &video_modes[8])) {
1012             tve_set_di_fmt(fbi, IPU_PIX_FMT_YUV444);
1013             tve_disable();
1014             tve_setup(TVOUT_FMT_1080P24);
1015             if (tve.blank == FB_BLANK_UNBLANK)
1016                 tve_enable();
1017         } else if (fb_mode_is_equal(fbi->mode, &video_modes[9])) {
1018             tve_set_di_fmt(fbi, IPU_PIX_FMT_GBR24);
1019             tve_disable();
1020             tve_setup(TVOUT_FMT_VGA_XGA);
1021             if (tve.blank == FB_BLANK_UNBLANK) {
1022                 tve_enable();
1023                 ipu_set_vga_delay(fbi, 1421, 803);
1024             }
1025         } else if (fb_mode_is_equal(fbi->mode, &video_modes[10])) {
1026             tve_set_di_fmt(fbi, IPU_PIX_FMT_GBR24);
1027             tve_disable();
1028             tve_setup(TVOUT_FMT_VGA_SXGA);
1029             if (tve.blank == FB_BLANK_UNBLANK) {
1030                 tve_enable();
1031                 ipu_set_vga_delay(fbi, 1504, 1030);
1032             }
1033         } else {
1034             tve_disable();
1035             tve_setup(TVOUT_FMT_OFF);
1036         }
1037         break;
1038     }
1039     case FB_EVENT_BLANK:
1040         if ((tve_fbi != fbi) || (fbi->mode == NULL))
1041             return 0;
1042 
1043         if (*((int *)event->data) == FB_BLANK_UNBLANK) {
1044             if (tve.blank != FB_BLANK_UNBLANK) {
1045                 if (fb_mode_is_equal(fbi->mode, &video_modes[0])) {
1046                     if (tve.cur_mode != TVOUT_FMT_NTSC) {
1047                         tve_disable();
1048                         tve_setup(TVOUT_FMT_NTSC);
1049                     }
1050                     tve_enable();
1051                 } else if (fb_mode_is_equal(fbi->mode,
1052                             &video_modes[1])) {
1053                     if (tve.cur_mode != TVOUT_FMT_PAL) {
1054                         tve_disable();
1055                         tve_setup(TVOUT_FMT_PAL);
1056                     }
1057                     tve_enable();
1058                 } else if (fb_mode_is_equal(fbi->mode,
1059                             &video_modes[2])) {
1060                     if (tve.cur_mode != TVOUT_FMT_720P60) {
1061                         tve_disable();
1062                         tve_setup(TVOUT_FMT_720P60);
1063                     }
1064                     tve_enable();
1065                 } else if (fb_mode_is_equal(fbi->mode,
1066                             &video_modes[3])) {
1067                     if (tve.cur_mode != TVOUT_FMT_720P30) {
1068                         tve_disable();
1069                         tve_setup(TVOUT_FMT_720P30);
1070                     }
1071                     tve_enable();
1072                 } else if (fb_mode_is_equal(fbi->mode,
1073                             &video_modes[4])) {
1074                     if (tve.cur_mode != TVOUT_FMT_1080I60) {
1075                         tve_disable();
1076                         tve_setup(TVOUT_FMT_1080I60);
1077                     }
1078                     tve_enable();
1079                 } else if (fb_mode_is_equal(fbi->mode,
1080                             &video_modes[5])) {
1081                     if (tve.cur_mode != TVOUT_FMT_1080I50) {
1082                         tve_disable();
1083                         tve_setup(TVOUT_FMT_1080I50);
1084                     }
1085                     tve_enable();
1086                 } else if (fb_mode_is_equal(fbi->mode,
1087                             &video_modes[6])) {
1088                     if (tve.cur_mode != TVOUT_FMT_1080P30) {
1089                         tve_disable();
1090                         tve_setup(TVOUT_FMT_1080P30);
1091                     }
1092                     tve_enable();
1093                 } else if (fb_mode_is_equal(fbi->mode,
1094                             &video_modes[7])) {
1095                     if (tve.cur_mode != TVOUT_FMT_1080P25) {
1096                         tve_disable();
1097                         tve_setup(TVOUT_FMT_1080P25);
1098                     }
1099                     tve_enable();
1100                 } else if (fb_mode_is_equal(fbi->mode,
1101                             &video_modes[8])) {
1102                     if (tve.cur_mode != TVOUT_FMT_1080P24) {
1103                         tve_disable();
1104                         tve_setup(TVOUT_FMT_1080P24);
1105                     }
1106                     tve_enable();
1107                 } else if (fb_mode_is_equal(fbi->mode,
1108                             &video_modes[9])) {
1109                     if (tve.cur_mode != TVOUT_FMT_VGA_XGA) {
1110                         tve_disable();
1111                         tve_setup(TVOUT_FMT_VGA_XGA);
1112                     }
1113                     tve_enable();
1114                     ipu_set_vga_delay(fbi, 1421, 803);
1115                 } else if (fb_mode_is_equal(fbi->mode,
1116                             &video_modes[10])) {
1117                     if (tve.cur_mode != TVOUT_FMT_VGA_SXGA) {
1118                         tve_disable();
1119                         tve_setup(TVOUT_FMT_VGA_SXGA);
1120                     }
1121                     tve_enable();
1122                     ipu_set_vga_delay(fbi, 1504, 1030);
1123                 } else {
1124                     tve_setup(TVOUT_FMT_OFF);
1125                 }
1126                 tve.blank = FB_BLANK_UNBLANK;
1127             }
1128         } else {
1129             tve_disable();
1130             tve.blank = FB_BLANK_POWERDOWN;
1131         }
1132         break;
1133     case FB_EVENT_SUSPEND:
1134         tve_suspend();
1135         break;
1136     case FB_EVENT_RESUME:
1137         tve_resume(fbi);
1138         break;
1139     }
1140     return 0;
1141 }

918 ~ 919 因为tve_fb_event被调用时不知道是不是tve的事件,如果不是,不做处理

922 ~ 943 FB_EVENT_FB_REGISTERED,那么要把NTSC PAL 720P加入到mode_list中,如果是rev2再加入一些mode,如果是mx53还支持XGA SXGA模式

944 ~ 1038 处理模式发生变化的情况

949 ~ 958 先检查新mode是否在tve_modelist中,不在的话则tve_disable

963 ~ 1032 1. 调用tve_set_di_fmt设置display input format; 2. disable tve; 3. tve_setup设置TVE 输出模式; 4.如果tve_fbi是UNBLANK的,那么还要调用tve_enable使能TVE

1033 ~ 1036 disable TVE,设置TVE


1039     case FB_EVENT_BLANK:
1040         if ((tve_fbi != fbi) || (fbi->mode == NULL))
1041             return 0;
1042 
1043         if (*((int *)event->data) == FB_BLANK_UNBLANK) {
1044             if (tve.blank != FB_BLANK_UNBLANK) {
1045                 if (fb_mode_is_equal(fbi->mode, &video_modes[0])) {
1046                     if (tve.cur_mode != TVOUT_FMT_NTSC) {
1047                         tve_disable();
1048                         tve_setup(TVOUT_FMT_NTSC);
1049                     }
1050                     tve_enable();
1051                 } else if (fb_mode_is_equal(fbi->mode,
1052                             &video_modes[1])) {
1053                     if (tve.cur_mode != TVOUT_FMT_PAL) {
1054                         tve_disable();
1055                         tve_setup(TVOUT_FMT_PAL);
1056                     }
1057                     tve_enable();
1058                 } else if (fb_mode_is_equal(fbi->mode,
1059                             &video_modes[2])) {
1060                     if (tve.cur_mode != TVOUT_FMT_720P60) {
1061                         tve_disable();
1062                         tve_setup(TVOUT_FMT_720P60);
1063                     }
1064                     tve_enable();
1065                 } else if (fb_mode_is_equal(fbi->mode,
1066                             &video_modes[3])) {
1067                     if (tve.cur_mode != TVOUT_FMT_720P30) {
1068                         tve_disable();
1069                         tve_setup(TVOUT_FMT_720P30);
1070                     }
1071                     tve_enable();
1072                 } else if (fb_mode_is_equal(fbi->mode,
1073                             &video_modes[4])) {
1074                     if (tve.cur_mode != TVOUT_FMT_1080I60) {
1075                         tve_disable();
1076                         tve_setup(TVOUT_FMT_1080I60);
1077                     }
1078                     tve_enable();
1079                 } else if (fb_mode_is_equal(fbi->mode,
1080                             &video_modes[5])) {
1081                     if (tve.cur_mode != TVOUT_FMT_1080I50) {
1082                         tve_disable();
1083                         tve_setup(TVOUT_FMT_1080I50);
1084                     }
1085                     tve_enable();
1086                 } else if (fb_mode_is_equal(fbi->mode,
1087                             &video_modes[6])) {
1088                     if (tve.cur_mode != TVOUT_FMT_1080P30) {
1089                         tve_disable();
1090                         tve_setup(TVOUT_FMT_1080P30);
1091                     }
1092                     tve_enable();
1093                 } else if (fb_mode_is_equal(fbi->mode,
1094                             &video_modes[7])) {
1095                     if (tve.cur_mode != TVOUT_FMT_1080P25) {
1096                         tve_disable();
1097                         tve_setup(TVOUT_FMT_1080P25);
1098                     }
1099                     tve_enable();
1100                 } else if (fb_mode_is_equal(fbi->mode,
1101                             &video_modes[8])) {
1102                     if (tve.cur_mode != TVOUT_FMT_1080P24) {
1103                         tve_disable();
1104                         tve_setup(TVOUT_FMT_1080P24);
1105                     }
1106                     tve_enable();
1107                 } else if (fb_mode_is_equal(fbi->mode,
1108                             &video_modes[9])) {
1109                     if (tve.cur_mode != TVOUT_FMT_VGA_XGA) {
1110                         tve_disable();
1111                         tve_setup(TVOUT_FMT_VGA_XGA);
1112                     }
1113                     tve_enable();
1114                     ipu_set_vga_delay(fbi, 1421, 803);
1115                 } else if (fb_mode_is_equal(fbi->mode,
1116                             &video_modes[10])) {
1117                     if (tve.cur_mode != TVOUT_FMT_VGA_SXGA) {
1118                         tve_disable();
1119                         tve_setup(TVOUT_FMT_VGA_SXGA);
1120                     }
1121                     tve_enable();
1122                     ipu_set_vga_delay(fbi, 1504, 1030);
1123                 } else {
1124                     tve_setup(TVOUT_FMT_OFF);
1125                 }
1126                 tve.blank = FB_BLANK_UNBLANK;
1127             }
1128         } else {
1129             tve_disable();
1130             tve.blank = FB_BLANK_POWERDOWN;
1131         }
1132         break;
1133     case FB_EVENT_SUSPEND:
1134         tve_suspend();
1135         break;
1136     case FB_EVENT_RESUME:
1137         tve_resume(fbi);
1138         break;
1139     }
1140     return 0;
1141 }


1128 ~ 1131 unblank操作,dsiable tve设置tve.blank为FB_BLANK_POWERDOWN

1043 ~ 1127 FB_BLANK_UNBLANK并且TVE当前状态不是FB_BLANK_UNBLANK,如果当前mode不是ffbi的当前模式,那么设置为当前模式,最后还要使能TVE


 821 static inline void tve_set_di_fmt(struct fb_info *fbi, unsigned int fmt)
 822 {
 823     mm_segment_t old_fs;
 824 
 825     if (fbi->fbops->fb_ioctl) {
 826         old_fs = get_fs();
 827         set_fs(KERNEL_DS);
 828         fbi->fbops->fb_ioctl(fbi, MXCFB_SET_DIFMT, (unsigned long)&fmt);
 829         set_fs(old_fs);
 830     }
 831 }

该函数调用fbi->fbops->fb_ioctl设置 display format,由于fmt是内核空间,而fb_ioctl系统调用会确定&fmt是用户空间,

所以需要把当前的fs设置为内核空间,避开这个检查。参见http://blog.chinaunix.net/space.php?uid=20564848&do=blog&cuid=2097853

 

771 static irqreturn_t tve_detect_handler(int irq, void *data)
 772 {
 773     u32 int_ctl = __raw_readl(tve.base + tve_regs->tve_int_cont_reg);
 774 
 775     /* disable INT first */
 776     int_ctl &= ~(CD_SM_INT | CD_LM_INT | CD_MON_END_INT);
 777     __raw_writel(int_ctl, tve.base + tve_regs->tve_int_cont_reg);
 778 
 779     __raw_writel(CD_MON_END_INT | CD_LM_INT | CD_SM_INT,
 780             tve.base + tve_regs->tve_stat_reg);
 781 
 782     schedule_delayed_work(&tve.cd_work, msecs_to_jiffies(1000));
 783 
 784     return IRQ_HANDLED;
 785 }


中断处理函数,首先disable INT清除中断状态位,然后清除掉tve_stat_reg中相应的状态位,这里我奇怪为什么要清除CD_MON_END_INT,因为tve_update_detect_status要使用这个标志呀


 615 static void tve_disable(void)
 616 {
 617     u32 reg;
 618     unsigned long lock_flags;
 619 
 620     spin_lock_irqsave(&tve_lock, lock_flags);
 621     if (enabled) {
 622         enabled = 0;
 623         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 624         __raw_writel(reg & ~TVE_ENABLE & ~TVE_IPU_CLK_ENABLE,
 625                 tve.base + tve_regs->tve_com_conf_reg);
 626         clk_disable(tve.clk);
 627         pr_debug("TVE power off.\n");
 628     }
 629     spin_unlock_irqrestore(&tve_lock, lock_flags);
 630 }
关闭TVE和TVE IPU clock,关闭tve.clk时钟,置位enable为0


 578 static void tve_enable(void)
 579 {
 580     u32 reg;
 581     unsigned long lock_flags;
 582 
 583     spin_lock_irqsave(&tve_lock, lock_flags);
 584     if (!enabled) {
 585         enabled = 1;
 586         clk_enable(tve.clk);
 587         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 588         __raw_writel(reg | TVE_IPU_CLK_ENABLE | TVE_ENABLE,
 589                     tve.base + tve_regs->tve_com_conf_reg);
 590         pr_debug("TVE power on.\n");
 591     }
 592 
 593     if (is_vga_mode()) {
 594         /* disable interrupt */
 595         pr_debug("TVE VGA disable cable detect.\n");
 596         __raw_writel(0xffffffff, tve.base + tve_regs->tve_stat_reg);
 597         __raw_writel(0, tve.base + tve_regs->tve_int_cont_reg);
 598     } else {
 599         /* enable interrupt */
 600         pr_debug("TVE TVE enable cable detect.\n");
 601         __raw_writel(0xffffffff, tve.base + tve_regs->tve_stat_reg);
 602         __raw_writel(CD_SM_INT | CD_LM_INT | CD_MON_END_INT,
 603                 tve.base + tve_regs->tve_int_cont_reg);
 604     }
 605 
 606     spin_unlock_irqrestore(&tve_lock, lock_flags);
 607 
 608     tve_dump_regs();
 609 }

584 ~ 591 使能tve.clk,使能TVE以及TVE IPU clock

593 ~ 598 对于TVE VGA模式关闭cable detect

598 ~ 604 对于其他的模式使能cable detect


 415 static int tve_setup(int mode)
 416 {
 417     u32 reg;
 418     struct clk *tve_parent_clk;
 419     unsigned long parent_clock_rate = 216000000, di1_clock_rate = 27000000;
 420     unsigned long tve_clock_rate = 216000000;
 421     unsigned long lock_flags;
 422 
 423     if (tve.cur_mode == mode)
 424         return 0;
 425 
 426     spin_lock_irqsave(&tve_lock, lock_flags);
 427 
 428     switch (mode) {
 429     case TVOUT_FMT_PAL:
 430     case TVOUT_FMT_NTSC:
 431         parent_clock_rate = 216000000;
 432         di1_clock_rate = 27000000;
 433         break;
 434     case TVOUT_FMT_720P60:
 435     case TVOUT_FMT_1080I60:
 436     case TVOUT_FMT_1080I50:
 437     case TVOUT_FMT_720P30:
 438     case TVOUT_FMT_1080P30:
 439     case TVOUT_FMT_1080P25:
 440     case TVOUT_FMT_1080P24:
 441         parent_clock_rate = 297000000;
 442         tve_clock_rate = 297000000;
 443         di1_clock_rate = 74250000;
 444         break;
 445     case TVOUT_FMT_VGA_XGA:
 446         parent_clock_rate = 260000000;
 447         tve_clock_rate = 130000000;
 448         di1_clock_rate = 65000000;
 449         break;
 450     case TVOUT_FMT_VGA_SXGA:
 451         parent_clock_rate = 216000000;
 452         di1_clock_rate = 108000000;
 453         break;
 454     }
 455     if (enabled)
 456         clk_disable(tve.clk);
 457 
 458     tve_parent_clk = clk_get_parent(tve.clk);
 459 
 460     clk_set_rate(tve_parent_clk, parent_clock_rate);
 461 
 462     tve_clock_rate = clk_round_rate(tve.clk, tve_clock_rate);
 463     clk_set_rate(tve.clk, tve_clock_rate);
 464 
 465     clk_enable(tve.clk);
 466     di1_clock_rate = clk_round_rate(tve.di_clk, di1_clock_rate);
 467     clk_set_rate(tve.di_clk, di1_clock_rate);
 468 
 469     tve.cur_mode = mode;
 470 
 471     /* select output video format */
 472     if (mode == TVOUT_FMT_PAL) {
 473         tve_disable_vga_mode();
 474         tve_set_tvout_mode(YPBPR);
 475         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 476         reg = (reg & ~TVE_STAND_MASK) | TVE_PAL_STAND;
 477         __raw_writel(reg, tve.base + tve_regs->tve_com_conf_reg);
 478         pr_debug("TVE: change to PAL video\n");
 479     } else if (mode == TVOUT_FMT_NTSC) {
 480         tve_disable_vga_mode();
 481         tve_set_tvout_mode(YPBPR);
 482         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 483         reg = (reg & ~TVE_STAND_MASK) | TVE_NTSC_STAND;
 484         __raw_writel(reg, tve.base + tve_regs->tve_com_conf_reg);
 485         pr_debug("TVE: change to NTSC video\n");
 486     } else if (mode == TVOUT_FMT_720P60) {
 487         tve_disable_vga_mode();
 488         if (!_is_tvout_mode_hd_compatible()) {
 489             tve_set_tvout_mode(YPBPR);
 490             pr_debug("The TV out mode is HD incompatible. Setting to YPBPR.");
 491         }
 492         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 493         reg = (reg & ~TVE_STAND_MASK) | TVE_HD720P60_STAND;
 494         __raw_writel(reg, tve.base + tve_regs->tve_com_conf_reg);
 495         pr_debug("TVE: change to 720P60 video\n");
 496     } else if (mode == TVOUT_FMT_720P30) {
 497         tve_disable_vga_mode();
 498         if (!_is_tvout_mode_hd_compatible()) {
 499             tve_set_tvout_mode(YPBPR);
 500             pr_debug("The TV out mode is HD incompatible. Setting to YPBPR.");
 501         }
 502         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 503         reg = (reg & ~TVE_STAND_MASK) | TVE_HD720P30_STAND;
 504         __raw_writel(reg, tve.base + tve_regs->tve_com_conf_reg);
 505         pr_debug("TVE: change to 720P30 video\n");
 506     } else if (mode == TVOUT_FMT_1080I60) {
 507         tve_disable_vga_mode();
 508         if (!_is_tvout_mode_hd_compatible()) {
 509             tve_set_tvout_mode(YPBPR);
 510             pr_debug("The TV out mode is HD incompatible. Setting to YPBPR.");
 511         }
 512         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 513         reg = (reg & ~TVE_STAND_MASK) | TVE_HD1080I60_STAND;
 514         __raw_writel(reg, tve.base + tve_regs->tve_com_conf_reg);
 515         pr_debug("TVE: change to 1080I60 video\n");
 516     } else if (mode == TVOUT_FMT_1080I50) {
 517         tve_disable_vga_mode();
 518         if (!_is_tvout_mode_hd_compatible()) {
 519             tve_set_tvout_mode(YPBPR);
 520             pr_debug("The TV out mode is HD incompatible. Setting to YPBPR.");
 521         }
 522         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 523         reg = (reg & ~TVE_STAND_MASK) | TVE_HD1080I50_STAND;
 524         __raw_writel(reg, tve.base + tve_regs->tve_com_conf_reg);
 525         pr_debug("TVE: change to 1080I50 video\n");
 526     } else if (mode == TVOUT_FMT_1080P30) {
 527         tve_disable_vga_mode();
 528         if (!_is_tvout_mode_hd_compatible()) {
 529             tve_set_tvout_mode(YPBPR);
 530             pr_debug("The TV out mode is HD incompatible. Setting to YPBPR.");
 531         }
 532         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 533         reg = (reg & ~TVE_STAND_MASK) | TVE_HD1080P30_STAND;
 534         __raw_writel(reg, tve.base + tve_regs->tve_com_conf_reg);
 535         pr_debug("TVE: change to 1080P30 video\n");
 536     } else if (mode == TVOUT_FMT_1080P25) {
 537         tve_disable_vga_mode();
 538         if (!_is_tvout_mode_hd_compatible()) {
 539             tve_set_tvout_mode(YPBPR);
 540             pr_debug("The TV out mode is HD incompatible. Setting to YPBPR.");
 541         }
 542         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 543         reg = (reg & ~TVE_STAND_MASK) | TVE_HD1080P25_STAND;
 544         __raw_writel(reg, tve.base + tve_regs->tve_com_conf_reg);
 545         pr_debug("TVE: change to 1080P25 video\n");
 546     } else if (mode == TVOUT_FMT_1080P24) {
 547         tve_disable_vga_mode();
 548         if (!_is_tvout_mode_hd_compatible()) {
 549             tve_set_tvout_mode(YPBPR);
 550             pr_debug("The TV out mode is HD incompatible. Setting to YPBPR.");
 551         }
 552         reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 553         reg = (reg & ~TVE_STAND_MASK) | TVE_HD1080P24_STAND;
 554         __raw_writel(reg, tve.base + tve_regs->tve_com_conf_reg);
 555         pr_debug("TVE: change to 1080P24 video\n");
 556     } else if ((mode == TVOUT_FMT_VGA_XGA) || (mode == TVOUT_FMT_VGA_SXGA)) {
 557         /* do not need cable detect */
 558         tve_setup_vga();
 559         pr_debug("TVE: change to VGA video\n");
 560     } else if (mode == TVOUT_FMT_OFF) {
 561         __raw_writel(0x0, tve.base + tve_regs->tve_com_conf_reg);
 562         pr_debug("TVE: change to OFF video\n");
 563     } else {
 564         pr_debug("TVE: no such video format.\n");
 565     }
 566 
 567     if (!enabled)
 568         clk_disable(tve.clk);
 569 
 570     spin_unlock_irqrestore(&tve_lock, lock_flags);
 571     return 0;
 572 }

428 ~ 454根据输出模式,设置时钟屏率,这里没搞明白这几个时钟的关系,以后再分析
455和465 先关闭再使能,为了保证所有情况下都打开tve.clk,以便下面对tve的操作。

458 ~ 467 设置parent clock, tve clk以及di1 clock的时钟频率

472 ~565 根据mode设置TVE的输出格式,这里没看明白的就是474行,传入的 mode为什么是YPBPR? 不是应该传入CVBS0吗,看不懂,觉得这里有问题,或者这里需要根据情况hard code;然后把输出模式设置到tve_com_conf_reg中

567 ~ 568 已经用完tve.clk,关闭它


 333 static void tve_set_tvout_mode(int mode)
 334 {
 335     u32 conf_reg;
 336 
 337     /* clear sync_ch and tvout_mode fields */
 338     conf_reg = __raw_readl(tve.base + tve_regs->tve_com_conf_reg);
 339     conf_reg &= ~(tve_reg_fields->sync_ch_mask |
 340                 tve_reg_fields->tvout_mode_mask);
 341 
 342     conf_reg = conf_reg & ~TVE_DAC_SAMPRATE_MASK;
 343     if (tve.revision == 2) {
 344         conf_reg = (conf_reg & ~TVEV2_DATA_SRC_MASK) |
 345             TVEV2_DATA_SRC_BUS_1;
 346         conf_reg = conf_reg & ~TVEV2_INP_VIDEO_FORM;
 347         conf_reg = conf_reg & ~TVEV2_P2I_CONV_EN;
 348     }
 349 
 350     conf_reg |=
 351         mode << tve_reg_fields->
 352         tvout_mode_offset | tvout_mode_to_channel_map[mode] <<
 353         tve_reg_fields->sync_ch_offset;
 354     __raw_writel(conf_reg, tve.base + tve_regs->tve_com_conf_reg);
 355 }

344 ~ 345 设置TVEV2_DATA_SRC 为BUS_1,这里还是hard code,其实我觉得也可以设置为BUS_2,那么数据就从IPU data bus2过来

346 设置input video的格式为YCbCr422

347 禁止progressive 到interlace的转换,我觉得如果是要得到NTSC PAL输出,最好使能它

350 ~ 355 根据给定的模式设置TV_OUT_MODE, 以及SYNC_CH_X_EN


小结:

分析后,如果想要实现自己的LCD+cvbs双屏输入,还需要定制一些参数,也许没看懂,做freescale的东西,真累。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mx51 TVOUT分析 的相关文章

  • ubuntu6-ubuntu采用tomcat搭建http下载服务器

    一 下载 1 1 tomcat官网 Apache Tomcat Welcome 1 2 ubuntu下载tomcat cd tmp sudo wget https dlcdn apache org tomcat tomcat 10 v10
  • 最新哔哩哔哩视频弹幕播放器源码+带后台/亲测无错误

    正文 最新哔哩哔哩视频弹幕播放器源码 43 带后台 亲测无错误 xff0c 此款播放器源码添加及修复了很多功能 xff0c 且所有源码均本地化 xff0c 不存在外链的情况 xff0c 测试环境 xff1a PHP7 0 43 MySQL5
  • UDP的socket绑定到IP地址后无法接受广播数据

    UDP的socket绑定到IP地址后无法接受广播数据 fannyth 05 11 10 18 37 由于考虑到我的程序要在多网卡的机器上运行 所以我将网卡的ip地址绑定到了socket server addr sin addr s addr
  • (四)可视化IMU数据

    一 xff29 xff2d xff35 数据格式 从KITTI的readme文件中https github com yanii kitti pcl blob master KITTI README TXT可以看到IMU里数据的格式 KITT
  • ROS项目开发实战(一)——STM32与ROS串口通信

    序 本文主要发布一些作者从零开始开发ROS的项目实战经验 xff0c 包括一些经验与本文遇到坑时的解决方案 xff0c ROS因为版本不同与开发环境不同在实际开发中会遇到各类问题 xff0c 下面就细细道来 一 环境搭建 本人开发环境 上位
  • I2C驱动体系结构一:驱动软件概念与对应硬件的关系

    一 概念 xff1a 1 设备 xff1a struct device xff1a 该数据结构是对物理设备的软件抽象 xff0c 比如I2C slave xff08 对应i2c client xff09 和I2C 适配器 xff08 对应i
  • TCP Server&Client socket实现(Ubuntu16.04)

    TCP Server amp Client socket实现 xff08 Ubuntu16 04 xff09 1 测试 xff1a 2 TCP Server3 TCP Client 1 测试 xff1a 2 TCP Server span
  • 关于为什么不能在头文件中包含变量定义的解释

    其实 xff0c 并不是C语言标准不允许在头文件中包含变量定义 xff0c 而是编译器本身产生了重复定义的错误 这时候有些人会很奇怪 xff0c 我不是写了 ifndef define endif这样的命令了吗 xff1f 如果你这样以为
  • 关于同一交换机下设置不同网段的PC的通信的猜测

    PC A IP 192 168 1 10 PC B IP 192 168 2 20 子网掩码24位 A和B都连接到一台二层交换机上 交换机上没有再接其他设备 A和B能否通信 从网上搜索了一下 发现有很多人问这个问题 但是大家的回答都很抽象
  • XP + Fedora 9 + Ubuntu8.10 安装过程点滴

    lt 64 page size 21cm 29 7cm margin 2cm P margin bottom 0 21cm gt XP 43 Fedora 9 43 Ubuntu8 10 安装过程点滴 fanfan 额外必须的软件 GRUB
  • 在Ubuntu下装MultiGet成功。。。

    本来用的是 xff0c deb包的1 1 2版 xff0c 下点不大的文件还可以 xff0c 可是我去下Ubuntu的DVD就出麻烦了 xff0c 早上把任务开起 xff0c 晚上回来居然什么都不见了 xff0c 连 Multiget程序都
  • 系统监控命令

    top命令 top c 在top命令显示界面显示出完整的进程名和启动参数 top H 在top命令中显示所有的线程 状 top p pid 这个pid可以是进程pid 也可以是线程pid 进程的pid就是该进程主线程的pid 该命令实际显示
  • 一个对齐关键字pack引起的副作用

    今天遇到一个很典型的因为没有留意pack关键字有效范围而引起的程序bug xff0c 觉得很有意思 xff0c 就记录下来 现象如下 xff1a 声明了一个数据结构 struct st data xff0c 这个数据结构中有一个成员是一个函
  • 什么是物联网?发展前景如何?

    物联网其实是互联网的一个延伸 xff0c 互联网的终端是计算机 PC 服务器 xff0c 我们运行的所有程序 xff0c 无非都是计算机和网络中的数据处理和数据传输 xff0c 除了计算机外 xff0c 没有涉及任何其他的终端 硬件 物联网
  • Linux上压缩文件的 5 种方法

    在 Linux 上有不少用于压缩文件的命令 最新最有效的一个方法是 xz xff0c 但是所有的方法都有节省磁盘空间和维护备份文件供以后使用的优点 在这篇文章中 xff0c 我们将比较这些压缩命令并指出显著的不同 tar tar 命令不是专
  • 新手如何从零开始学习unity

    自从 unity5发布免费过后 xff0c 有很多独立游戏开发者转向unity游戏开发 xff0c unity的优势就是多终端 跨平台打包 xff0c 入门也快 xff0c 很多人感觉自己的英文不好 xff0c 就觉得学不会 xff0c 其
  • stm32零基础入门,应学习那些知识

    1 首先我们先看看与STM32相关的文档 我们假定大家已经对STM32的书籍或者文档有一定的理解 如不理解 xff0c 请立即阅读STM32的文档 xff0c 以获取最基本的知识点 如果你手上拥有ST官方主推的STM32神舟系列的板子 xf
  • Java如何实现二维码扫码授权登陆

    如今的生活中 xff0c 登录网站也变得如此简单 xff0c 当你已经登录一微信时 xff0c 当你想要登录另一个网站时 xff0c 只需扫码便可 xff0c 可是大家知道用Java怎么实现扫码授权吗 本文讲述的就是关于如何用Java实现扫
  • Postman安装与简单使用

    Postman使用参考文档 xff1a 1 官方英文文档 2 chrome插件整理的 postman中文使用教程 Postman一款非常流行的API调试工具 其实 xff0c 开发人员用的更多 因为测试人员做接口测试会有更多选择 xff0c

随机推荐

  • c语言入门基础

    C语言的结构 1 Hello world 简单来说 xff0c 一个C程序就是由若干头文件和函数组成 include 包含头文件 主函数 int main printf Hello World return 0 include 就是一条预处
  • 单片机串行口介绍

    介绍 串行口是单片机与外界进行信息交换的工具 xff0c 8051单片机的通信方式有两种 xff1a 并行通信 数据的各位同时发送或接收 串行通信 数据一位一位次序发送或接收 串行通信的方式 异步通信 用一个起始位0表示字符的开始 xff0
  • 51单片机中断机制(定时器)

    单片机中断简介 52单片机一共有6个中断源 xff0c 它们的符号 xff0c 名称以及各产生的条件分别如下 xff1a INT0 外部中断0 xff0c 由P3 2端口线引入 xff0c 低电平或下降沿引起 INT1 外部中断1 xff0
  • 什么叫51单片机最小系统

    单片机最小系统 或者称为最小应用系统 是指用最少的元件组成的单片机可以工作的系统 对51系列单片机来说 最小系统一般应该包括 单片机 晶振电路 复位电路 下面给出一个51单片机的最小系统电路图 说明 复位电路 由电容串联电阻构成 由图并结合
  • 嵌入式系统C编程之错误处理

    一 错误概念 1 1 错误分类 从严重性而言 xff0c 程序错误可分为致命性和非致命性两类 对于致命性错误 xff0c 无法执行恢复动作 xff0c 最多只能在用户屏幕上打印出错消息或将其写入日志文件 xff0c 然后终止程序 而对于非致
  • 补光灯的单片机开发设计

    说到摄影灯 xff0c 相信每个人都一定听说过闪光灯和补光灯 那它们是怎么由来的呢 又是怎么达到了你想要的效果呢 不论是闪光灯还是补光灯 xff0c 它们都有一个共同点 xff0c 那就是由NY8A051D单片机开发而来 xff0c 单片机
  • 单片机C语言如何产生随机数

    单片机C语言如何产生随机数 随机数在单片机的应用中也是很多的 xff0c 当然产生随机数的方法有很多 xff0c 当中有一个就是利用单片机定时器 xff0c 取出未知的定时器THX和TLX的值 xff0c 再加以运算得到一个规定范围内的随机
  • 使用mac终端编译运行c程序

    使用mac终端编译运行c程序 本文介绍如何利用mac自带文本编辑软件编写c代码 xff0c 并在mac自带终端内用命令行编译运行c程序 1 在mac上安装c编译环境 打开mac自带的终端 在终端命令行里输入xcode select inst
  • HtmlParser 一个不错的网站爬虫工具

    有时候我们需要在网上获取自己需要的内容时 xff0c 而且需求量达到一定程度时 xff0c 就要通过代码来实现重复的操作 当用Java来帮我们解决这个问题时 xff0c 我们又如何通过Java来过滤掉多余的内容 xff0c 剩余自己想要的信
  • 因为jsoup,再见了我的htmlparser

    jsoup 一款Java 的HTML解析器 xff0c 可直接解析某个URL地址 HTML文本内容 它提供了一套非常省力的API xff0c 可通过DOM xff0c CSS以及类似于jQuery的操作方法来取出和操作数据 这里是jsoup
  • Python 当前时间是那一年第几周的周几

    isocalendar 函数 返回 xff08 XX年 xff0c 一年中的第几周 xff0c 这一天是周几 xff09 gt gt gt from datetime import datetime gt gt gt datetime no
  • 对Socket CAN的理解(1)——【CAN总线原理】

    转载请注明出处 xff1a http blog csdn net Righthek 谢谢 xff01 由于Socket CAN涉及到CAN总线协议 套接字 Linux网络设备驱动等 因此 xff0c 为了能够全面地了解Socket CAN的
  • 对Socket CAN的理解(2)——【Socket的原理及使用】

    转载请注明出处 xff1a http blog csdn net Righthek 谢谢 xff01 为了能够对Socket CAN的深入理解 xff0c 我们需要了解Socket的机制 Socket的中文翻译为 插座 xff0c 在计算机
  • 【智能家居篇】wifi网络结构(上)

    转载请注明出处 xff1a http blog csdn net Righthek 谢谢 xff01 WIFI是什么 xff0c 相信大家都知道 xff0c 这里就不作说明了 我们需要做的是深入了解其工作原理 xff0c 包括软硬件 网络结
  • 【智能家居篇】wifi网络结构(下)

    转载请注明出处 xff1a http blog csdn net Righthek 谢谢 xff01 由于WIFI网络具有移动性 xff0c 同时WIFI以无线电波作为传输媒介 xff0c 这种媒介本质上是开放的 xff0c 且容易被拦截
  • 【智能家居篇】wifi网络接入原理(上)——扫描Scanning

    转载请注明出处 xff1a http blog csdn net Righthek 谢谢 xff01 对于低头党来说 xff0c 在使用WIFI功能时 xff0c 经常性的操作是打开手机上的WIFI设备 xff0c 搜索到心目中的热点 xf
  • 【智能家居篇】wifi网络接入原理(下)——关联Association

    转载请注明出处 xff1a http blog csdn net Righthek 谢谢 xff01 认证完成后 xff0c 下一步就是关联 xff08 Association xff09 工作站与基站进行关联 xff0c 以便获得网络的完
  • 【智能家居篇】wifi驱动的理解(3)——usb接口在wifi模块中的角色

    转载请注明出处 xff1a http blog csdn net Righthek 谢谢 xff01 上一篇文章已经提到USB接口在wifi模块中的最重要两个函数是usb read port 和usb write port 那它们是怎么和w
  • 【智能家居篇】wifi驱动的理解(4)——usb接口在wifi模块中的角色

    转载请注明出处 xff1a http blog csdn net Righthek 谢谢 xff01 还有1天就到2017年了 xff0c 回顾整个2016年至此 xff0c 都没发表过一篇技术文章 做软件开发已有5 6年 xff0c 作为
  • mx51 TVOUT分析

    1397 static int init enable tve setup char options 1398 1399 g enable tve 61 true 1400 1401 return 1 1402 1403 setup 34