之前选择lvds channel都是在uboot的env里面写ldb=sin0这样,但是现在要动态去修改也就是在系统跑起来之后做这个事。于是先看这个channel是怎么选择的。
在ldb.c中看code
static int __init ldb_setup(char *options) { if (!strcmp(options, "spl0")) g_ldb_mode = LDB_SPL_DI0; else if (!strcmp(options, "spl1")) g_ldb_mode = LDB_SPL_DI1; else if (!strcmp(options, "dul0")) g_ldb_mode = LDB_DUL_DI0; else if (!strcmp(options, "dul1")) g_ldb_mode = LDB_DUL_DI1; else if (!strcmp(options, "sin0")) g_ldb_mode = LDB_SIN0; else if (!strcmp(options, "sin1")) g_ldb_mode = LDB_SIN1; else if (!strcmp(options, "sep0")) g_ldb_mode = LDB_SEP0; else if (!strcmp(options, "sep1")) g_ldb_mode = LDB_SEP1; return 1; } __setup("ldb=", ldb_setup);这里获取了cmd line里的参数,然后这个参数怎么用呢
其实就是写了两个register
writel(reg, ldb->control_reg);
writel(reg, ldb->control_reg);
这两个register在cmd里的sin0的时候
是161,0
在sin1的时候是172,256.
那在哪里改呢,先看ldb和fbmem.c直接怎么通信
有个ldb_fb_event,这里接受fb_notify的消息
fbmem.c中会发消息,所以先在这里加代码
case FB_EVENT_CHANR_CHANNEL: printk("matt-FB_EVENT_CHANR_CHANNEL \n"); mo=*((int *)event->data); if(mo == 0)//channel sin0 { ldb->mode=5; writel(161, ldb->control_reg); ldb->setting[0].ch_mask = 3; ldb->setting[0].ch_val = 1; }else{ ldb->mode=6; writel(172, ldb->control_reg); ldb->setting[0].ch_mask = 12; ldb->setting[0].ch_val = 12; } reg = readl(ldb->gpr3_reg); printk("matt-before reg=%d\n",reg); reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK); channel1 = ldb->mode - LDB_SIN0; shift1 = LVDS0_MUX_CTL_OFFS + channel1 * LVDS_MUX_CTL_WIDTH; reg |= ROUTE_IPU_DI(0, mo) << shift1; printk("matt-channel=%d,reg=%d\n",channel1,reg); writel(reg, ldb->gpr3_reg); break;
然后到fbmem.c中的ioctl中去加代码
case FBIOSET_CHANNEL: printk("matt-FBIOSET_CHANNEL\n"); if (copy_from_user(&ret1, argp, sizeof(ret1))) return -EFAULT; event.data=&ret1; if (!lock_fb_info(info)) return -ENODEV; event.info = info; fb_notifier_call_chain(FB_EVENT_CHANR_CHANNEL, &event); unlock_fb_info(info); ret = copy_to_user(argp, &ret, sizeof(ret)) ? -EFAULT : 0;
然后在外面写应用c
#include <linux/fb.h> #include <stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include <linux/ioctl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <linux/fb.h> #include <sys/mman.h> #include <math.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <linux/fb.h> #include <sys/mman.h> #define FBIOSET_CHANNEL 0x4622 struct fb_var_screeninfo vinfo; void main(int argc, char * argv[]) { int fd = 0; int channel; int x =0; channel=atoi(argv[1]); printf("start ioctl \n"); // printf("matt-argc=%d\n",argc); fd = open("/dev/fb0",O_RDWR); if (fd < 0) { printf("matt-Open Dev Mem0 Error!\n"); } sleep(5); printf("matt-channel=%d\n",channel); //选择channel /* if (ioctl(fd,FBIOSET_CHANNEL,&channel)) { printf("Error writeing variable information/n"); exit(3); } */ if (ioctl(fd,FBIOGET_VSCREENINFO,&vinfo)) { printf("Error reading variable information/n"); exit(3); } close(fd); done: exit(0);
