织梦CMS - 轻松建站从此开始!

罗索

mx51 TVOUT分析

落鹤生 发布于 2012-07-02 10:13 点击:次 
分析后,如果想要实现自己的LCD+cvbs双屏输入,还需要定制一些参数,也许没看懂,做freescale的东西,真累。
TAG:

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的东西,真累。

(kickxxx)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201207/16130.html]
本文出处:CSDN博客 作者:kickxxx 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容