之前选择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);