int vga_switch_default_screen(void) { int i, mode_num = DEFAULT_MODE; const struct fb_videomode *mode = NULL; static int init_flag = 0; if (ddev == NULL) { printk("vga-ddc: No DDC Dev.\n"); return -ENODEV; } mode = vga_find_best_mode(); if (mode) { printk("vga-ddc: best mode %dx%d@%d[pixclock-%ld KHZ]\n", mode->xres, mode->yres, mode->refresh, PICOS2KHZ(mode->pixclock)); for(i = 0; i < get_vga_mode_len(); i++) { if(fb_mode_is_equal(&sda7123_vga_mode[i], mode)) { mode_num = i + 1; break; } } } return mode_num; }
static void sh_mobile_fb_reconfig(struct fb_info *info) { struct sh_mobile_lcdc_chan *ch = info->par; struct fb_videomode mode1, mode2; struct fb_event event; int evnt = FB_EVENT_MODE_CHANGE_ALL; if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par)) /* More framebuffer users are active */ return; fb_var_to_videomode(&mode1, &ch->display_var); fb_var_to_videomode(&mode2, &info->var); if (fb_mode_is_equal(&mode1, &mode2)) return; /* Display has been re-plugged, framebuffer is free now, reconfigure */ if (fb_set_var(info, &ch->display_var) < 0) /* Couldn't reconfigure, hopefully, can continue as before */ return; info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8); /* * fb_set_var() calls the notifier change internally, only if * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a * user event, we have to call the chain ourselves. */ event.info = info; event.data = &mode1; fb_notifier_call_chain(evnt, &event); }
static int lcdif_init(struct mxc_dispdrv_handle *disp, struct mxc_dispdrv_setting *setting) { int ret, i; struct mxc_lcdif_data *lcdif = mxc_dispdrv_getdata(disp); struct fsl_mxc_lcd_platform_data *plat_data = lcdif->pdev->dev.platform_data; struct fb_videomode *modedb = lcdif_modedb; int modedb_sz = lcdif_modedb_sz; /* use platform defined ipu/di */ setting->dev_id = plat_data->ipu_id; setting->disp_id = plat_data->disp_id; ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str, modedb, modedb_sz, NULL, setting->default_bpp); if (!ret) { fb_videomode_to_var(&setting->fbi->var, &modedb[0]); setting->if_fmt = plat_data->default_ifmt; } INIT_LIST_HEAD(&setting->fbi->modelist); for (i = 0; i < modedb_sz; i++) { struct fb_videomode m; fb_var_to_videomode(&m, &setting->fbi->var); if (fb_mode_is_equal(&m, &modedb[i])) { fb_add_videomode(&modedb[i], &setting->fbi->modelist); break; } } return ret; }
static int lcd_set_mode(struct rk_display_device *device, struct fb_videomode *mode) { struct rk29fb_screen screen; if(fb_mode_is_equal(&rk29_lcd_mode, mode)) { lcd_mode2screen(mode, &screen); FB_Switch_Screen(&screen, 1); lcd_current_mode = (struct fb_videomode *)&rk29_lcd_mode; } return 0; }
static int mipi_dsi_lcd_init(struct mipi_dsi_info *mipi_dsi, struct mxc_dispdrv_setting *setting) { int i, size, err; struct fb_videomode *mipi_lcd_modedb; struct fb_videomode mode; struct device *dev = &mipi_dsi->pdev->dev; for (i = 0; i < ARRAY_SIZE(mipi_dsi_lcd_db); i++) { if (!strcmp(mipi_dsi->lcd_panel, mipi_dsi_lcd_db[i].lcd_panel)) { mipi_dsi->lcd_callback = &mipi_dsi_lcd_db[i].lcd_callback; break; } } if (i == ARRAY_SIZE(mipi_dsi_lcd_db)) { dev_err(dev, "failed to find supported lcd panel.\n"); return -EINVAL; } mipi_dsi->lcd_callback->get_mipi_lcd_videomode(&mipi_lcd_modedb, &size, &mipi_dsi->lcd_config); err = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str, mipi_lcd_modedb, size, NULL, setting->default_bpp); if (err != 1) fb_videomode_to_var(&setting->fbi->var, mipi_lcd_modedb); INIT_LIST_HEAD(&setting->fbi->modelist); for (i = 0; i < size; i++) { fb_var_to_videomode(&mode, &setting->fbi->var); if (fb_mode_is_equal(&mode, mipi_lcd_modedb + i)) { err = fb_add_videomode(mipi_lcd_modedb + i, &setting->fbi->modelist); mipi_dsi->mode = mipi_lcd_modedb + i; break; } } if ((err < 0) || (size == i)) { dev_err(dev, "failed to add videomode.\n"); return err; } return 0; }
static int rk1000_cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode) { int i; for(i = 0; i < ARRAY_SIZE(rk1000_cvbs_mode); i++) { if(fb_mode_is_equal(&rk1000_cvbs_mode[i], mode)) { if( ((i + 1) != rk1000.mode) ) { cvbs_monspecs.mode_set = i + 1; cvbs_monspecs.mode = (struct fb_videomode *)&rk1000_cvbs_mode[i]; } return 0; } } return -1; }
static int cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode) { int i; for (i = 0; i < ARRAY_SIZE(rk3036_cvbs_mode); i++) { if (fb_mode_is_equal(&rk3036_cvbs_mode[i], mode)) { if (rk3036_tve->mode != &rk3036_cvbs_mode[i]) { rk3036_tve->mode = (struct fb_videomode *)&rk3036_cvbs_mode[i]; if (rk3036_tve->enable && !rk3036_tve->suspend) dac_enable(false); tve_switch_fb(rk3036_tve->mode, 1); dac_enable(true); } return 0; } } TVEDBG("%s\n", __func__); return -1; }
static int ldb_disp_init(struct mxc_dispdrv_handle *disp, struct mxc_dispdrv_setting *setting) { int ret = 0, i; struct ldb_data *ldb = mxc_dispdrv_getdata(disp); struct fsl_mxc_ldb_platform_data *plat_data = ldb->pdev->dev.platform_data; struct resource *res; uint32_t base_addr; uint32_t reg, setting_idx; uint32_t ch_mask = 0, ch_val = 0; uint32_t ipu_id, disp_id; /* if input format not valid, make RGB666 as default*/ if (!valid_mode(setting->if_fmt)) { dev_warn(&ldb->pdev->dev, "Input pixel format not valid" " use default RGB666\n"); setting->if_fmt = IPU_PIX_FMT_RGB666; } if (!ldb->inited) { char di_clk[] = "ipu1_di0_clk"; char ldb_clk[] = "ldb_di0_clk"; int lvds_channel = 0; setting_idx = 0; res = platform_get_resource(ldb->pdev, IORESOURCE_MEM, 0); if (IS_ERR(res)) return -ENOMEM; base_addr = res->start; ldb->reg = ioremap(base_addr, res->end - res->start + 1); ldb->control_reg = ldb->reg + 2; ldb->gpr3_reg = ldb->reg + 3; ldb->lvds_bg_reg = regulator_get(&ldb->pdev->dev, plat_data->lvds_bg_reg); if (!IS_ERR(ldb->lvds_bg_reg)) { regulator_set_voltage(ldb->lvds_bg_reg, 2500000, 2500000); regulator_enable(ldb->lvds_bg_reg); } /* ipu selected by platform data setting */ setting->dev_id = plat_data->ipu_id; reg = readl(ldb->control_reg); /* refrence resistor select */ reg &= ~LDB_BGREF_RMODE_MASK; if (plat_data->ext_ref) reg |= LDB_BGREF_RMODE_EXT; else reg |= LDB_BGREF_RMODE_INT; /* TODO: now only use SPWG data mapping for both channel */ reg &= ~(LDB_BIT_MAP_CH0_MASK | LDB_BIT_MAP_CH1_MASK); reg |= LDB_BIT_MAP_CH0_SPWG | LDB_BIT_MAP_CH1_SPWG; /* channel mode setting */ reg &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK); reg &= ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK); if (bits_per_pixel(setting->if_fmt) == 24) reg |= LDB_DATA_WIDTH_CH0_24 | LDB_DATA_WIDTH_CH1_24; else reg |= LDB_DATA_WIDTH_CH0_18 | LDB_DATA_WIDTH_CH1_18; if (g_ldb_mode) ldb->mode = g_ldb_mode; else ldb->mode = plat_data->mode; if ((ldb->mode == LDB_SIN0) || (ldb->mode == LDB_SIN1)) { ret = ldb->mode - LDB_SIN0; if (plat_data->disp_id != ret) { dev_warn(&ldb->pdev->dev, "change IPU DI%d to IPU DI%d for LDB " "channel%d.\n", plat_data->disp_id, ret, ret); plat_data->disp_id = ret; } } else if (((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1)) && (cpu_is_mx6q() || cpu_is_mx6dl())) { if (plat_data->disp_id == plat_data->sec_disp_id) { dev_err(&ldb->pdev->dev, "For LVDS separate mode," "two DIs should be different!\n"); return -EINVAL; } if (((!plat_data->disp_id) && (ldb->mode == LDB_SEP1)) || ((plat_data->disp_id) && (ldb->mode == LDB_SEP0))) { dev_dbg(&ldb->pdev->dev, "LVDS separate mode:" "swap DI configuration!\n"); ipu_id = plat_data->ipu_id; disp_id = plat_data->disp_id; plat_data->ipu_id = plat_data->sec_ipu_id; plat_data->disp_id = plat_data->sec_disp_id; plat_data->sec_ipu_id = ipu_id; plat_data->sec_disp_id = disp_id; } } if (ldb->mode == LDB_SPL_DI0) { reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0; setting->disp_id = 0; } else if (ldb->mode == LDB_SPL_DI1) { reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1; setting->disp_id = 1; } else if (ldb->mode == LDB_DUL_DI0) { reg &= ~LDB_SPLIT_MODE_EN; reg |= LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0; setting->disp_id = 0; } else if (ldb->mode == LDB_DUL_DI1) { reg &= ~LDB_SPLIT_MODE_EN; reg |= LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1; setting->disp_id = 1; } else if (ldb->mode == LDB_SIN0) { reg &= ~LDB_SPLIT_MODE_EN; setting->disp_id = plat_data->disp_id; if (setting->disp_id == 0) reg |= LDB_CH0_MODE_EN_TO_DI0; else reg |= LDB_CH0_MODE_EN_TO_DI1; ch_mask = LDB_CH0_MODE_MASK; ch_val = reg & LDB_CH0_MODE_MASK; } else if (ldb->mode == LDB_SIN1) { reg &= ~LDB_SPLIT_MODE_EN; setting->disp_id = plat_data->disp_id; if (setting->disp_id == 0) reg |= LDB_CH1_MODE_EN_TO_DI0; else reg |= LDB_CH1_MODE_EN_TO_DI1; ch_mask = LDB_CH1_MODE_MASK; ch_val = reg & LDB_CH1_MODE_MASK; } else { /* separate mode*/ setting->disp_id = plat_data->disp_id; /* first output is LVDS0 or LVDS1 */ if (ldb->mode == LDB_SEP0) lvds_channel = 0; else lvds_channel = 1; reg &= ~LDB_SPLIT_MODE_EN; if ((lvds_channel == 0) && (setting->disp_id == 0)) reg |= LDB_CH0_MODE_EN_TO_DI0; else if ((lvds_channel == 0) && (setting->disp_id == 1)) reg |= LDB_CH0_MODE_EN_TO_DI1; else if ((lvds_channel == 1) && (setting->disp_id == 0)) reg |= LDB_CH1_MODE_EN_TO_DI0; else reg |= LDB_CH1_MODE_EN_TO_DI1; ch_mask = lvds_channel ? LDB_CH1_MODE_MASK : LDB_CH0_MODE_MASK; ch_val = reg & ch_mask; if (bits_per_pixel(setting->if_fmt) == 24) { if (lvds_channel == 0) reg &= ~LDB_DATA_WIDTH_CH1_24; else reg &= ~LDB_DATA_WIDTH_CH0_24; } else { if (lvds_channel == 0) reg &= ~LDB_DATA_WIDTH_CH1_18; else reg &= ~LDB_DATA_WIDTH_CH0_18; } } writel(reg, ldb->control_reg); if (ldb->mode < LDB_SIN0) { ch_mask = LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK; ch_val = reg & (LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK); } /* clock setting */ if ((cpu_is_mx6q() || cpu_is_mx6dl()) && ((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1))) ldb_clk[6] += lvds_channel; else ldb_clk[6] += setting->disp_id; ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev, ldb_clk); if (IS_ERR(ldb->setting[setting_idx].ldb_di_clk)) { dev_err(&ldb->pdev->dev, "get ldb clk0 failed\n"); iounmap(ldb->reg); return PTR_ERR(ldb->setting[setting_idx].ldb_di_clk); } di_clk[3] += setting->dev_id; di_clk[7] += setting->disp_id; ldb->setting[setting_idx].di_clk = clk_get(&ldb->pdev->dev, di_clk); if (IS_ERR(ldb->setting[setting_idx].di_clk)) { dev_err(&ldb->pdev->dev, "get di clk0 failed\n"); iounmap(ldb->reg); return PTR_ERR(ldb->setting[setting_idx].di_clk); } dev_dbg(&ldb->pdev->dev, "ldb_clk to di clk: %s -> %s\n", ldb_clk, di_clk); /* fb notifier for clk setting */ ldb->nb.notifier_call = ldb_fb_event, ret = fb_register_client(&ldb->nb); if (ret < 0) { iounmap(ldb->reg); return ret; } ldb->inited = true; } else { /* second time for separate mode */ char di_clk[] = "ipu1_di0_clk"; char ldb_clk[] = "ldb_di0_clk"; int lvds_channel; if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1) || (ldb->mode == LDB_DUL_DI0) || (ldb->mode == LDB_DUL_DI1) || (ldb->mode == LDB_SIN0) || (ldb->mode == LDB_SIN1)) { dev_err(&ldb->pdev->dev, "for second ldb disp" "ldb mode should in separate mode\n"); return -EINVAL; } setting_idx = 1; if (cpu_is_mx6q() || cpu_is_mx6dl()) { setting->dev_id = plat_data->sec_ipu_id; setting->disp_id = plat_data->sec_disp_id; } else { setting->dev_id = plat_data->ipu_id; setting->disp_id = !plat_data->disp_id; } if (setting->disp_id == ldb->setting[0].di) { dev_err(&ldb->pdev->dev, "Err: for second ldb disp in" "separate mode, DI should be different!\n"); return -EINVAL; } /* second output is LVDS0 or LVDS1 */ if (ldb->mode == LDB_SEP0) lvds_channel = 1; else lvds_channel = 0; reg = readl(ldb->control_reg); if ((lvds_channel == 0) && (setting->disp_id == 0)) reg |= LDB_CH0_MODE_EN_TO_DI0; else if ((lvds_channel == 0) && (setting->disp_id == 1)) reg |= LDB_CH0_MODE_EN_TO_DI1; else if ((lvds_channel == 1) && (setting->disp_id == 0)) reg |= LDB_CH1_MODE_EN_TO_DI0; else reg |= LDB_CH1_MODE_EN_TO_DI1; ch_mask = lvds_channel ? LDB_CH1_MODE_MASK : LDB_CH0_MODE_MASK; ch_val = reg & ch_mask; if (bits_per_pixel(setting->if_fmt) == 24) { if (lvds_channel == 0) reg |= LDB_DATA_WIDTH_CH0_24; else reg |= LDB_DATA_WIDTH_CH1_24; } else { if (lvds_channel == 0) reg |= LDB_DATA_WIDTH_CH0_18; else reg |= LDB_DATA_WIDTH_CH1_18; } writel(reg, ldb->control_reg); /* clock setting */ if (cpu_is_mx6q() || cpu_is_mx6dl()) ldb_clk[6] += lvds_channel; else ldb_clk[6] += setting->disp_id; ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev, ldb_clk); if (IS_ERR(ldb->setting[setting_idx].ldb_di_clk)) { dev_err(&ldb->pdev->dev, "get ldb clk1 failed\n"); return PTR_ERR(ldb->setting[setting_idx].ldb_di_clk); } di_clk[3] += setting->dev_id; di_clk[7] += setting->disp_id; ldb->setting[setting_idx].di_clk = clk_get(&ldb->pdev->dev, di_clk); if (IS_ERR(ldb->setting[setting_idx].di_clk)) { dev_err(&ldb->pdev->dev, "get di clk1 failed\n"); return PTR_ERR(ldb->setting[setting_idx].di_clk); } dev_dbg(&ldb->pdev->dev, "ldb_clk to di clk: %s -> %s\n", ldb_clk, di_clk); } ldb->setting[setting_idx].ch_mask = ch_mask; ldb->setting[setting_idx].ch_val = ch_val; if (cpu_is_mx6q() || cpu_is_mx6dl()) ldb_ipu_ldb_route(setting->dev_id, setting->disp_id, ldb); /* * ldb_di0_clk -> ipux_di0_clk * ldb_di1_clk -> ipux_di1_clk */ clk_set_parent(ldb->setting[setting_idx].di_clk, ldb->setting[setting_idx].ldb_di_clk); /* must use spec video mode defined by driver */ ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str, ldb_modedb, ldb_modedb_sz, NULL, setting->default_bpp); if (ret != 1) fb_videomode_to_var(&setting->fbi->var, &ldb_modedb[0]); INIT_LIST_HEAD(&setting->fbi->modelist); for (i = 0; i < ldb_modedb_sz; i++) { struct fb_videomode m; fb_var_to_videomode(&m, &setting->fbi->var); if (fb_mode_is_equal(&m, &ldb_modedb[i])) { fb_add_videomode(&ldb_modedb[i], &setting->fbi->modelist); break; } } /* save current ldb setting for fb notifier */ ldb->setting[setting_idx].active = true; ldb->setting[setting_idx].ipu = setting->dev_id; ldb->setting[setting_idx].di = setting->disp_id; return ret; }
/*! * This function is called by the driver framework to initialize the LDB * device. * * @param dev The device structure for the LDB passed in by the * driver framework. * * @return Returns 0 on success or negative error code on error */ static int ldb_probe(struct platform_device *pdev) { int ret = 0, i, ipu_di, ipu_di_pix_fmt[2]; bool primary = false, find_1080p = false; struct resource *res; struct ldb_platform_data *plat_data = pdev->dev.platform_data; mm_segment_t old_fs; struct clk *ldb_clk_parent; unsigned long ldb_clk_prate = 455000000; struct fb_var_screeninfo *var[2]; uint32_t reg; struct device *temp; int mxc_ldb_major; const struct fb_videomode *mode; struct class *mxc_ldb_class; if (g_enable_ldb == false) return -ENODEV; spin_lock_init(&ldb_lock); g_ldb_dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (IS_ERR(res)) return -ENODEV; memset(&ldb, 0, sizeof(struct ldb_data)); enabled[0] = enabled[1] = false; var[0] = var[1] = NULL; if (g_boot_cmd) { ldb.chan_mode_opt = g_chan_mode_opt; ldb.chan_bit_map[0] = g_chan_bit_map[0]; ldb.chan_bit_map[1] = g_chan_bit_map[1]; } ldb.base_addr = res->start; ldb_reg = ioremap(ldb.base_addr, res->end - res->start + 1); ldb.control_reg = ldb_reg + 2; INIT_LIST_HEAD(&ldb.modelist); for (i = 0; i < mxcfb_ldb_modedb_sz; i++) fb_add_videomode(&mxcfb_ldb_modedb[i], &ldb.modelist); for (i = 0; i < num_registered_fb; i++) { if ((registered_fb[i]->var.sync & FB_SYNC_EXT) && (registered_fb[i]->var.vmode == FB_VMODE_NONINTERLACED)) { ldb.fbi[i] = registered_fb[i]; mode = fb_match_mode(&ldb.fbi[i]->var, &ldb.modelist); if (mode) { dev_dbg(g_ldb_dev, "fb mode found\n"); fb_videomode_to_var(&ldb.fbi[i]->var, mode); } else { dev_warn(g_ldb_dev, "can't find video mode\n"); goto err0; } /* * Default ldb mode: * 1080p: DI0 split, SPWG or DI1 split, SPWG * others: single, SPWG */ if (g_boot_cmd == false) { if (fb_mode_is_equal(mode, &mxcfb_ldb_modedb[0])) { if (strcmp(ldb.fbi[i]->fix.id, "DISP3 BG") == 0) { ldb.chan_mode_opt = LDB_SPL_DI0; dev_warn(g_ldb_dev, "default di0 split mode\n"); } else if (strcmp(ldb.fbi[i]->fix.id, "DISP3 BG - DI1") == 0) { ldb.chan_mode_opt = LDB_SPL_DI1; dev_warn(g_ldb_dev, "default di1 split mode\n"); } ldb.chan_bit_map[0] = LDB_BIT_MAP_SPWG; ldb.chan_bit_map[1] = LDB_BIT_MAP_SPWG; find_1080p = true; } else if (!find_1080p) { if (strcmp(ldb.fbi[i]->fix.id, "DISP3 BG") == 0) { ldb.chan_mode_opt = LDB_SIN_DI0; ldb.chan_bit_map[0] = LDB_BIT_MAP_SPWG; dev_warn(g_ldb_dev, "default di0 single mode\n"); } else if (strcmp(ldb.fbi[i]->fix.id, "DISP3 BG - DI1") == 0) { ldb.chan_mode_opt = LDB_SIN_DI1; ldb.chan_bit_map[1] = LDB_BIT_MAP_SPWG; dev_warn(g_ldb_dev, "default di1 single mode\n"); } } } acquire_console_sem(); fb_blank(ldb.fbi[i], FB_BLANK_POWERDOWN); release_console_sem(); if (i == 0) primary = true; if (ldb.fbi[1] != NULL) break; } } /* * We cannot support two LVDS panel with different pixel clock rates * except that one's pixel clock rate is two times of the others'. */ if (ldb.fbi[1] && ldb.fbi[0] != NULL) { if (ldb.fbi[0]->var.pixclock != ldb.fbi[1]->var.pixclock && ldb.fbi[0]->var.pixclock != 2 * ldb.fbi[1]->var.pixclock && ldb.fbi[1]->var.pixclock != 2 * ldb.fbi[0]->var.pixclock) return -EINVAL; } ldb.bgref_rmode = plat_data->ext_ref; ldb.lvds_bg_reg = regulator_get(&pdev->dev, plat_data->lvds_bg_reg); if (!IS_ERR(ldb.lvds_bg_reg)) { regulator_set_voltage(ldb.lvds_bg_reg, 2500000, 2500000); regulator_enable(ldb.lvds_bg_reg); } for (i = 0; i < 2; i++) { if (ldb.fbi[i] != NULL) { if (strcmp(ldb.fbi[i]->fix.id, "DISP3 BG") == 0) ipu_di = 0; else if (strcmp(ldb.fbi[i]->fix.id, "DISP3 BG - DI1") == 0) ipu_di = 1; else { dev_err(g_ldb_dev, "Wrong framebuffer\n"); goto err0; } var[ipu_di] = &ldb.fbi[i]->var; if (ldb.fbi[i]->fbops->fb_ioctl) { old_fs = get_fs(); set_fs(KERNEL_DS); ldb.fbi[i]->fbops->fb_ioctl(ldb.fbi[i], MXCFB_GET_DIFMT, (unsigned long)&(ipu_di_pix_fmt[ipu_di])); set_fs(old_fs); } else { dev_err(g_ldb_dev, "Can't get framebuffer " "information\n"); goto err0; } if (!valid_mode(ipu_di_pix_fmt[ipu_di])) { dev_err(g_ldb_dev, "Unsupport pixel format " "for ldb input\n"); goto err0; } reg = __raw_readl(ldb.control_reg); if (var[ipu_di]->sync & FB_SYNC_VERT_HIGH_ACT) { if (ipu_di == 0) __raw_writel((reg & ~LDB_DI0_VS_POL_MASK) | LDB_DI0_VS_POL_ACT_HIGH, ldb.control_reg); else __raw_writel((reg & ~LDB_DI1_VS_POL_MASK) | LDB_DI1_VS_POL_ACT_HIGH, ldb.control_reg); } else { if (ipu_di == 0) __raw_writel((reg & ~LDB_DI0_VS_POL_MASK) | LDB_DI0_VS_POL_ACT_LOW, ldb.control_reg); else __raw_writel((reg & ~LDB_DI1_VS_POL_MASK) | LDB_DI1_VS_POL_ACT_LOW, ldb.control_reg); } /* TODO:Set the correct pll4 rate for all situations */ if (ipu_di == 1) { ldb.ldb_di_clk[1] = clk_get(&pdev->dev, "ldb_di1_clk"); ldb_clk_parent = clk_get_parent(ldb.ldb_di_clk[1]); clk_set_rate(ldb_clk_parent, ldb_clk_prate); clk_put(ldb.ldb_di_clk[1]); } else { ldb.ldb_di_clk[0] = clk_get(&pdev->dev, "ldb_di0_clk"); ldb_clk_parent = clk_get_parent(ldb.ldb_di_clk[0]); clk_set_rate(ldb_clk_parent, ldb_clk_prate); clk_put(ldb.ldb_di_clk[0]); } } } reg = __raw_readl(ldb.control_reg); if (ldb.bgref_rmode == LDB_EXT_REF) __raw_writel((reg & ~LDB_BGREF_RMODE_MASK) | LDB_BGREF_RMODE_EXT, ldb.control_reg); else __raw_writel((reg & ~LDB_BGREF_RMODE_MASK) | LDB_BGREF_RMODE_INT, ldb.control_reg); switch (ldb.chan_mode_opt) { case LDB_SIN_DI0: if (var[0] == NULL) { dev_err(g_ldb_dev, "Can't find framebuffer on DI0\n"); break; } reg = __raw_readl(ldb.control_reg); if (bits_per_pixel(ipu_di_pix_fmt[0]) == 24) __raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) | LDB_DATA_WIDTH_CH0_24, ldb.control_reg); else if (bits_per_pixel(ipu_di_pix_fmt[0]) == 18) __raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) | LDB_DATA_WIDTH_CH0_18, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG) __raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) | LDB_BIT_MAP_CH0_SPWG, ldb.control_reg); else __raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) | LDB_BIT_MAP_CH0_JEIDA, ldb.control_reg); ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk"); clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7); clk_enable(ldb.ldb_di_clk[0]); clk_put(ldb.ldb_di_clk[0]); reg = __raw_readl(ldb.control_reg); __raw_writel((reg & ~LDB_CH0_MODE_MASK) | LDB_CH0_MODE_EN_TO_DI0, ldb.control_reg); ldb.ch_working[0] = true; break; case LDB_SIN_DI1: if (var[1] == NULL) { dev_err(g_ldb_dev, "Can't find framebuffer on DI1\n"); break; } reg = __raw_readl(ldb.control_reg); if (bits_per_pixel(ipu_di_pix_fmt[1]) == 24) __raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) | LDB_DATA_WIDTH_CH1_24, ldb.control_reg); else if (bits_per_pixel(ipu_di_pix_fmt[1]) == 18) __raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) | LDB_DATA_WIDTH_CH1_18, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG) __raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) | LDB_BIT_MAP_CH1_SPWG, ldb.control_reg); else __raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) | LDB_BIT_MAP_CH1_JEIDA, ldb.control_reg); ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk"); clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7); clk_enable(ldb.ldb_di_clk[1]); clk_put(ldb.ldb_di_clk[1]); reg = __raw_readl(ldb.control_reg); __raw_writel((reg & ~LDB_CH1_MODE_MASK) | LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg); ldb.ch_working[1] = true; break; case LDB_SEP: if (var[0] == NULL || var[1] == NULL) { dev_err(g_ldb_dev, "Can't find framebuffers on DI0/1\n"); break; } reg = __raw_readl(ldb.control_reg); if (bits_per_pixel(ipu_di_pix_fmt[0]) == 24) __raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) | LDB_DATA_WIDTH_CH0_24, ldb.control_reg); else if (bits_per_pixel(ipu_di_pix_fmt[0]) == 18) __raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) | LDB_DATA_WIDTH_CH0_18, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (bits_per_pixel(ipu_di_pix_fmt[1]) == 24) __raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) | LDB_DATA_WIDTH_CH1_24, ldb.control_reg); else if (bits_per_pixel(ipu_di_pix_fmt[1]) == 18) __raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) | LDB_DATA_WIDTH_CH1_18, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG) __raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) | LDB_BIT_MAP_CH0_SPWG, ldb.control_reg); else __raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) | LDB_BIT_MAP_CH0_JEIDA, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG) __raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) | LDB_BIT_MAP_CH1_SPWG, ldb.control_reg); else __raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) | LDB_BIT_MAP_CH1_JEIDA, ldb.control_reg); ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk"); clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7); clk_enable(ldb.ldb_di_clk[0]); clk_put(ldb.ldb_di_clk[0]); ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk"); clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7); clk_enable(ldb.ldb_di_clk[1]); clk_put(ldb.ldb_di_clk[1]); reg = __raw_readl(ldb.control_reg); __raw_writel((reg & ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK)) | LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg); ldb.ch_working[0] = true; ldb.ch_working[1] = true; break; case LDB_DUL_DI0: case LDB_SPL_DI0: if (var[0] == NULL) { dev_err(g_ldb_dev, "Can't find framebuffer on DI0\n"); break; } reg = __raw_readl(ldb.control_reg); if (bits_per_pixel(ipu_di_pix_fmt[0]) == 24) __raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK)) | LDB_DATA_WIDTH_CH0_24 | LDB_DATA_WIDTH_CH1_24, ldb.control_reg); else if (bits_per_pixel(ipu_di_pix_fmt[0]) == 18) __raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK)) | LDB_DATA_WIDTH_CH0_18 | LDB_DATA_WIDTH_CH1_18, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG) __raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) | LDB_BIT_MAP_CH0_SPWG, ldb.control_reg); else __raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) | LDB_BIT_MAP_CH0_JEIDA, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG) __raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) | LDB_BIT_MAP_CH1_SPWG, ldb.control_reg); else __raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) | LDB_BIT_MAP_CH1_JEIDA, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (ldb.chan_mode_opt == LDB_SPL_DI0) __raw_writel(reg | LDB_SPLIT_MODE_EN, ldb.control_reg); ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk"); ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk"); if (ldb.chan_mode_opt == LDB_DUL_DI0) { clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7); } else { clk_set_rate(ldb.ldb_di_clk[0], 2*ldb_clk_prate/7); clk_set_rate(ldb.ldb_di_clk[1], 2*ldb_clk_prate/7); } clk_enable(ldb.ldb_di_clk[0]); clk_enable(ldb.ldb_di_clk[1]); clk_put(ldb.ldb_di_clk[0]); clk_put(ldb.ldb_di_clk[1]); reg = __raw_readl(ldb.control_reg); __raw_writel((reg & ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK)) | LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0, ldb.control_reg); ldb.ch_working[0] = true; ldb.ch_working[1] = true; break; case LDB_DUL_DI1: case LDB_SPL_DI1: if (var[1] == NULL) { dev_err(g_ldb_dev, "Can't find framebuffer on DI1\n"); break; } reg = __raw_readl(ldb.control_reg); if (bits_per_pixel(ipu_di_pix_fmt[1]) == 24) __raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK)) | LDB_DATA_WIDTH_CH0_24 | LDB_DATA_WIDTH_CH1_24, ldb.control_reg); else if (bits_per_pixel(ipu_di_pix_fmt[1]) == 18) __raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK)) | LDB_DATA_WIDTH_CH0_18 | LDB_DATA_WIDTH_CH1_18, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG) __raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) | LDB_BIT_MAP_CH0_SPWG, ldb.control_reg); else __raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) | LDB_BIT_MAP_CH0_JEIDA, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG) __raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) | LDB_BIT_MAP_CH1_SPWG, ldb.control_reg); else __raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) | LDB_BIT_MAP_CH1_JEIDA, ldb.control_reg); reg = __raw_readl(ldb.control_reg); if (ldb.chan_mode_opt == LDB_SPL_DI1) __raw_writel(reg | LDB_SPLIT_MODE_EN, ldb.control_reg); ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk"); ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk"); if (ldb.chan_mode_opt == LDB_DUL_DI1) { clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7); } else { clk_set_rate(ldb.ldb_di_clk[0], 2*ldb_clk_prate/7); clk_set_rate(ldb.ldb_di_clk[1], 2*ldb_clk_prate/7); } clk_enable(ldb.ldb_di_clk[0]); clk_enable(ldb.ldb_di_clk[1]); clk_put(ldb.ldb_di_clk[0]); clk_put(ldb.ldb_di_clk[1]); reg = __raw_readl(ldb.control_reg); __raw_writel((reg & ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK)) | LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg); ldb.ch_working[0] = true; ldb.ch_working[1] = true; break; default: break; } mxc_ldb_major = register_chrdev(0, "mxc_ldb", &mxc_ldb_fops); if (mxc_ldb_major < 0) { dev_err(g_ldb_dev, "Unable to register MXC LDB as a char " "device\n"); ret = mxc_ldb_major; goto err0; } mxc_ldb_class = class_create(THIS_MODULE, "mxc_ldb"); if (IS_ERR(mxc_ldb_class)) { dev_err(g_ldb_dev, "Unable to create class for MXC LDB\n"); ret = PTR_ERR(mxc_ldb_class); goto err1; } temp = device_create(mxc_ldb_class, NULL, MKDEV(mxc_ldb_major, 0), NULL, "mxc_ldb"); if (IS_ERR(temp)) { dev_err(g_ldb_dev, "Unable to create class device for " "MXC LDB\n"); ret = PTR_ERR(temp); goto err2; } ret = fb_register_client(&nb); if (ret < 0) goto err2; if (primary && ldb.fbi[0] != NULL) { acquire_console_sem(); fb_blank(ldb.fbi[0], FB_BLANK_UNBLANK); release_console_sem(); fb_show_logo(ldb.fbi[0], 0); } return ret; err2: class_destroy(mxc_ldb_class); err1: unregister_chrdev(mxc_ldb_major, "mxc_ldb"); err0: iounmap(ldb_reg); return ret; }
static int lcdif_init(struct mxc_dispdrv_handle *disp, struct mxc_dispdrv_setting *setting) { int ret, i; struct mxc_lcdif_data *lcdif = mxc_dispdrv_getdata(disp); struct fsl_mxc_lcd_platform_data *plat_data = lcdif->pdev->dev.platform_data; struct fb_videomode *modedb = lcdif_modedb; int modedb_sz = lcdif_modedb_sz; struct fsl_video_timing *custom_timing; /* use platform defined ipu/di */ setting->dev_id = plat_data->ipu_id; setting->disp_id = plat_data->disp_id; if (plat_data->lcd0_timing != NULL) { custom_timing = plat_data->lcd0_timing; lcdif_modedb[0].pixclock = PICOS2KHZ(custom_timing->pixclock); lcdif_modedb[0].xres = custom_timing->hres; lcdif_modedb[0].left_margin = custom_timing->hfp; lcdif_modedb[0].right_margin = custom_timing->hbp; lcdif_modedb[0].hsync_len = custom_timing->hsw; lcdif_modedb[0].yres = custom_timing->vres; lcdif_modedb[0].upper_margin = custom_timing->vfp; lcdif_modedb[0].lower_margin = custom_timing->vbp; lcdif_modedb[0].vsync_len = custom_timing->vsw; } if (plat_data->lcd1_timing != NULL) { custom_timing = plat_data->lcd1_timing; lcdif_modedb[1].pixclock = PICOS2KHZ(custom_timing->pixclock); lcdif_modedb[1].xres = custom_timing->hres; lcdif_modedb[1].left_margin = custom_timing->hfp; lcdif_modedb[1].right_margin = custom_timing->hbp; lcdif_modedb[1].hsync_len = custom_timing->hsw; lcdif_modedb[1].yres = custom_timing->vres; lcdif_modedb[1].upper_margin = custom_timing->vfp; lcdif_modedb[1].lower_margin = custom_timing->vbp; lcdif_modedb[1].vsync_len = custom_timing->vsw; } ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str, modedb, modedb_sz, NULL, setting->default_bpp); if (!ret) { fb_videomode_to_var(&setting->fbi->var, &modedb[0]); setting->if_fmt = plat_data->default_ifmt; } INIT_LIST_HEAD(&setting->fbi->modelist); for (i = 0; i < modedb_sz; i++) { struct fb_videomode m; fb_var_to_videomode(&m, &setting->fbi->var); if (fb_mode_is_equal(&m, &modedb[i])) { fb_add_videomode(&modedb[i], &setting->fbi->modelist); break; } } return ret; }
int tve_fb_event(struct notifier_block *nb, unsigned long val, void *v) { struct fb_event *event = v; struct fb_info *fbi = event->info; switch (val) { case FB_EVENT_FB_REGISTERED: pr_debug("fb registered event\n"); if ((tve_fbi != NULL) || strcmp(fbi->fix.id, "DISP3 BG - DI1")) break; tve_fbi = fbi; fb_add_videomode(&video_modes[0], &tve_fbi->modelist); fb_add_videomode(&video_modes[1], &tve_fbi->modelist); break; case FB_EVENT_MODE_CHANGE: if (tve_fbi != fbi) break; if (!fbi->mode) { tve_disable(); tve.cur_mode = TVOUT_FMT_OFF; return 0; } pr_debug("fb mode change event: xres=%d, yres=%d\n", fbi->mode->xres, fbi->mode->yres); tve_disable(); if (fb_mode_is_equal(fbi->mode, &video_modes[0])) { tve_setup(TVOUT_FMT_NTSC); tve_enable(); } else if (fb_mode_is_equal(fbi->mode, &video_modes[1])) { tve_setup(TVOUT_FMT_PAL); tve_enable(); } else { tve_setup(TVOUT_FMT_OFF); } break; case FB_EVENT_BLANK: if ((tve_fbi != fbi) || (fbi->mode == NULL)) return 0; if (*((int *)event->data) == FB_BLANK_UNBLANK) { if (fb_mode_is_equal(fbi->mode, &video_modes[0])) { if (tve.cur_mode != TVOUT_FMT_NTSC) { tve_disable(); tve_setup(TVOUT_FMT_NTSC); } tve_enable(); } else if (fb_mode_is_equal(fbi->mode, &video_modes[1])) { if (tve.cur_mode != TVOUT_FMT_PAL) { tve_disable(); tve_setup(TVOUT_FMT_PAL); } tve_enable(); } else { tve_setup(TVOUT_FMT_OFF); } } else tve_disable(); break; } return 0; }
static int ldb_fb_pre_setup(struct fb_info *fbi) { int ipu_di = 0; struct clk *di_clk, *ldb_clk_parent; unsigned long ldb_clk_prate = 455000000; fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var, &fbi->modelist); if (!fbi->mode) { dev_warn(g_ldb_dev, "can not find mode for xres=%d, yres=%d\n", fbi->var.xres, fbi->var.yres); return 0; } if (fbi->fbops->fb_ioctl) { mm_segment_t old_fs; old_fs = get_fs(); set_fs(KERNEL_DS); fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_DI, (unsigned long)&ipu_di); fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_BLANK, (unsigned int)(&ldb.blank[ipu_di])); set_fs(old_fs); /* * Default ldb mode: * 1080p: DI0 split, SPWG or DI1 split, SPWG * others: single, SPWG */ if (ldb.chan_mode_opt == LDB_NO_MODE) { if (fb_mode_is_equal(fbi->mode, &mxcfb_ldb_modedb[0])) { if (ipu_di == 0) { ldb.chan_mode_opt = LDB_SPL_DI0; dev_warn(g_ldb_dev, "default di0 split mode\n"); } else { ldb.chan_mode_opt = LDB_SPL_DI1; dev_warn(g_ldb_dev, "default di1 split mode\n"); } ldb.chan_bit_map[0] = LDB_BIT_MAP_SPWG; ldb.chan_bit_map[1] = LDB_BIT_MAP_SPWG; } else if (fb_mode_is_equal(fbi->mode, &mxcfb_ldb_modedb[1])) { if (ipu_di == 0) { ldb.chan_mode_opt = LDB_SIN_DI0; ldb.chan_bit_map[0] = LDB_BIT_MAP_SPWG; dev_warn(g_ldb_dev, "default di0 single mode\n"); } else { ldb.chan_mode_opt = LDB_SIN_DI1; ldb.chan_bit_map[1] = LDB_BIT_MAP_SPWG; dev_warn(g_ldb_dev, "default di1 single mode\n"); } } } /* TODO:Set the correct pll4 rate for all situations */ if (ipu_di == 1) { ldb.ldb_di_clk[1] = clk_get(g_ldb_dev, "ldb_di1_clk"); di_clk = clk_get(g_ldb_dev, "ipu_di1_clk"); ldb_clk_parent = clk_get_parent(ldb.ldb_di_clk[1]); clk_set_rate(ldb_clk_parent, ldb_clk_prate); clk_set_parent(di_clk, ldb.ldb_di_clk[1]); clk_put(di_clk); clk_put(ldb.ldb_di_clk[1]); } else { ldb.ldb_di_clk[0] = clk_get(g_ldb_dev, "ldb_di0_clk"); di_clk = clk_get(g_ldb_dev, "ipu_di0_clk"); ldb_clk_parent = clk_get_parent(ldb.ldb_di_clk[0]); clk_set_rate(ldb_clk_parent, ldb_clk_prate); clk_set_parent(di_clk, ldb.ldb_di_clk[0]); clk_put(di_clk); clk_put(ldb.ldb_di_clk[0]); } switch (ldb.chan_mode_opt) { case LDB_SIN_DI0: ldb.ldb_di_clk[0] = clk_get(g_ldb_dev, "ldb_di0_clk"); clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7); if (ldb.blank[0] == FB_BLANK_UNBLANK && clk_get_usecount(ldb.ldb_di_clk[0]) == 0) clk_enable(ldb.ldb_di_clk[0]); clk_put(ldb.ldb_di_clk[0]); break; case LDB_SIN_DI1: ldb.ldb_di_clk[1] = clk_get(g_ldb_dev, "ldb_di1_clk"); clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7); if (ldb.blank[1] == FB_BLANK_UNBLANK && clk_get_usecount(ldb.ldb_di_clk[1]) == 0) clk_enable(ldb.ldb_di_clk[1]); clk_put(ldb.ldb_di_clk[1]); break; case LDB_SEP: if (ipu_di == 0) { ldb.ldb_di_clk[0] = clk_get(g_ldb_dev, "ldb_di0_clk"); clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7); if (ldb.blank[0] == FB_BLANK_UNBLANK && clk_get_usecount(ldb.ldb_di_clk[0]) == 0) clk_enable(ldb.ldb_di_clk[0]); clk_put(ldb.ldb_di_clk[0]); } else { ldb.ldb_di_clk[1] = clk_get(g_ldb_dev, "ldb_di1_clk"); clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7); if (ldb.blank[1] == FB_BLANK_UNBLANK && clk_get_usecount(ldb.ldb_di_clk[1]) == 0) clk_enable(ldb.ldb_di_clk[1]); clk_put(ldb.ldb_di_clk[1]); } break; case LDB_DUL_DI0: case LDB_SPL_DI0: ldb.ldb_di_clk[0] = clk_get(g_ldb_dev, "ldb_di0_clk"); ldb.ldb_di_clk[1] = clk_get(g_ldb_dev, "ldb_di1_clk"); if (ldb.chan_mode_opt == LDB_DUL_DI0) { clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7); } else { clk_set_rate(ldb.ldb_di_clk[0], 2*ldb_clk_prate/7); clk_set_rate(ldb.ldb_di_clk[1], 2*ldb_clk_prate/7); } if (ldb.blank[0] == FB_BLANK_UNBLANK) { if (clk_get_usecount(ldb.ldb_di_clk[0]) == 0) clk_enable(ldb.ldb_di_clk[0]); if (clk_get_usecount(ldb.ldb_di_clk[1]) == 0) clk_enable(ldb.ldb_di_clk[1]); } clk_put(ldb.ldb_di_clk[0]); clk_put(ldb.ldb_di_clk[1]); break; case LDB_DUL_DI1: case LDB_SPL_DI1: ldb.ldb_di_clk[0] = clk_get(g_ldb_dev, "ldb_di0_clk"); ldb.ldb_di_clk[1] = clk_get(g_ldb_dev, "ldb_di1_clk"); if (ldb.chan_mode_opt == LDB_DUL_DI1) { clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7); } else { clk_set_rate(ldb.ldb_di_clk[0], 2*ldb_clk_prate/7); clk_set_rate(ldb.ldb_di_clk[1], 2*ldb_clk_prate/7); } if (ldb.blank[1] == FB_BLANK_UNBLANK) { if (clk_get_usecount(ldb.ldb_di_clk[0]) == 0) clk_enable(ldb.ldb_di_clk[0]); if (clk_get_usecount(ldb.ldb_di_clk[1]) == 0) clk_enable(ldb.ldb_di_clk[1]); } clk_put(ldb.ldb_di_clk[0]); clk_put(ldb.ldb_di_clk[1]); break; default: break; } if (ldb.blank[ipu_di] == FB_BLANK_UNBLANK) ldb_enable(ipu_di); } return 0; }