static void vga_set_modelist(void) { int i, j = 0, modelen = 0; struct fb_videomode *mode = NULL; struct list_head *modelist = &ddev->modelist; struct fb_monspecs *specs = &ddev->specs; int pixclock; fb_destroy_modelist(modelist); for(i = 1; i <= specs->modedb_len; i++) { mode = &specs->modedb[i % specs->modedb_len]; //printk("%d %d %d %d %d %d %d %d %d %d %d %d %d\n",mode->refresh,mode->xres,mode->yres,mode->pixclock,mode->left_margin,mode->right_margin,mode->upper_margin, \ // mode->lower_margin,mode->hsync_len,mode->vsync_len, mode->sync,mode->vmode,mode->flag); pixclock = PICOS2KHZ(mode->pixclock); if (pixclock < (specs->dclkmax / 1000)) { for (j = 0; j < get_vga_mode_len(); j++) { if (default_modedb[j].xres == mode->xres && default_modedb[j].yres == mode->yres && (default_modedb[j].refresh == mode->refresh || default_modedb[j].refresh == mode->refresh + 1 || default_modedb[j].refresh == mode->refresh -1 )) { fb_add_videomode(&default_modedb[j], modelist); modelen++; break; } } } } ddev->modelen = modelen; }
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; }
void lcd_register_display_sysfs(void *devdata) { INIT_LIST_HEAD(&lcd_modelist); fb_add_videomode(&rk29_lcd_mode, &lcd_modelist); display_device_lcd = rk_display_device_register(&display_lcd, NULL, devdata); rk_display_device_enable(display_device_lcd); }
static void stmfb_enumerate_modes(struct stmfb_info *i) { int n; const stm_mode_line_t *mode; struct fb_videomode vm; INIT_LIST_HEAD(&i->info.modelist); for (n=0; n<STVTG_TIMING_MODE_COUNT; n++) { if (!(mode = stm_display_output_get_display_mode(i->pFBMainOutput, n))) continue; stmfb_encode_videomode(mode, &vm); /* * Create a state mode database of just the supported modes for module * parameter parsing. */ i->videomodedb[n] = vm; /* * Add to the framework's mode list for sysfs */ fb_add_videomode(&vm, &i->info.modelist); } /* the modelist is automatically destroyed by unregister_framebuffer() so * we only have to worry about leaks on error paths before we are successfully * registered. */ }
static void adf_fbdev_fill_modelist(struct adf_fbdev *fbdev) { struct drm_mode_modeinfo *modelist; struct fb_videomode fbmode; size_t n_modes, i; int ret = 0; n_modes = adf_interface_modelist(fbdev->intf, NULL, 0); modelist = kzalloc(sizeof(modelist[0]) * n_modes, GFP_KERNEL); if (!modelist) { dev_warn(fbdev->info->dev, "allocating new modelist failed; keeping old modelist\n"); return; } adf_interface_modelist(fbdev->intf, modelist, n_modes); fb_destroy_modelist(&fbdev->info->modelist); for (i = 0; i < n_modes; i++) { adf_modeinfo_to_fb_videomode(&modelist[i], &fbmode); ret = fb_add_videomode(&fbmode, &fbdev->info->modelist); if (ret < 0) dev_warn(fbdev->info->dev, "adding mode %s to modelist failed: %d\n", modelist[i].name, ret); } kfree(modelist); }
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 void vga_set_default_modelist(void) { int i, j = 0, modelen = 0; struct fb_videomode *mode = NULL; struct list_head *modelist = &ddev->modelist; struct fb_monspecs *specs = &ddev->specs; int pixclock; fb_destroy_modelist(modelist); modelen = get_vga_mode_len(); for(i = 0; i < modelen; i++) { fb_add_videomode(&default_modedb[i], modelist); } ddev->modelen = modelen; }
int rk1000_register_display_cvbs(struct device *parent) { int i; memset(&cvbs_monspecs, 0, sizeof(struct rk1000_monspecs)); INIT_LIST_HEAD(&cvbs_monspecs.modelist); for(i = 0; i < ARRAY_SIZE(rk1000_cvbs_mode); i++) fb_add_videomode(&rk1000_cvbs_mode[i], &cvbs_monspecs.modelist); if(rk1000.mode < TVOUT_YPbPr_720x480p_60) { cvbs_monspecs.mode = (struct fb_videomode *)&(rk1000_cvbs_mode[rk1000.mode - 1]); cvbs_monspecs.mode_set = rk1000.mode; } else { cvbs_monspecs.mode = (struct fb_videomode *)&(rk1000_cvbs_mode[0]); cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC; } cvbs_monspecs.ddev = rk_display_device_register(&display_rk1000_cvbs, parent, NULL); rk1000.cvbs = &cvbs_monspecs; if(rk1000.mode < TVOUT_YPbPr_720x480p_60) rk_display_device_enable(cvbs_monspecs.ddev); return 0; }
/*! * 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 void det_worker(struct work_struct *work) { BYTE HPD, HPDChange ; char event_string[16]; char *envp[] = { event_string, NULL }; CheckHDMITX(&HPD, &HPDChange); if (HPDChange) { /* cable connection changes */ if (HPD) { ite661x.cable_plugin = 1; sprintf(event_string, "EVENT=plugin"); /* make sure fb is powerdown */ acquire_console_sem(); fb_blank(ite661x.fbi, FB_BLANK_POWERDOWN); release_console_sem(); if (ite661x_read_edid(ite661x.fbi) < 0) dev_err(&ite661x.client->dev, "ite661x: read edid fail\n"); else { ParseEDID(ite661x.edid + 128); if (ite661x.fbi->monspecs.modedb_len > 0) { int i; const struct fb_videomode *mode; struct fb_videomode m; fb_destroy_modelist(&ite661x.fbi->modelist); for (i = 0; i < ite661x.fbi->monspecs.modedb_len; i++) { /*FIXME now we do not support interlaced mode */ if (!(ite661x.fbi->monspecs.modedb[i].vmode & FB_VMODE_INTERLACED)) fb_add_videomode(&ite661x.fbi->monspecs.modedb[i], &ite661x.fbi->modelist); } fb_var_to_videomode(&m, &ite661x.fbi->var); mode = fb_find_nearest_mode(&m, &ite661x.fbi->modelist); fb_videomode_to_var(&ite661x.fbi->var, mode); ite661x.fbi->var.activate |= FB_ACTIVATE_FORCE; acquire_console_sem(); ite661x.fbi->flags |= FBINFO_MISC_USEREVENT; fb_set_var(ite661x.fbi, &ite661x.fbi->var); ite661x.fbi->flags &= ~FBINFO_MISC_USEREVENT; release_console_sem(); } acquire_console_sem(); fb_blank(ite661x.fbi, FB_BLANK_UNBLANK); release_console_sem(); HDMITX_SetOutput(); } } else { ite661x.cable_plugin = 0; sprintf(event_string, "EVENT=plugout"); acquire_console_sem(); fb_blank(ite661x.fbi, FB_BLANK_POWERDOWN); release_console_sem(); DisableAudioOutput(); DisableVideoOutput(); } kobject_uevent_env(&ite661x.pdev->dev.kobj, KOBJ_CHANGE, envp); } enable_irq(ite661x.client->irq); }
static void det_worker(struct work_struct *work) { int dat; char event_string[16]; char *envp[] = { event_string, NULL }; dev_dbg(&sii902x.pdev->dev, "%s\n", __func__); dat = i2c_smbus_read_byte_data(sii902x.client, 0x3D); if (dat & 0x1) { /* cable connection changes */ if (dat & 0x4) { sii902x.cable_plugin = 1; dev_dbg(&sii902x.pdev->dev, "EVENT=plugin\n"); sprintf(event_string, "EVENT=plugin"); if (sii902x_read_edid(sii902x.fbi) < 0) dev_err(&sii902x.client->dev, "Sii902x: read edid fail\n"); else { if (sii902x.fbi->monspecs.modedb_len > 0) { int i; const struct fb_videomode *mode; struct fb_videomode m; fb_destroy_modelist(&sii902x.fbi->modelist); for (i = 0; i < sii902x.fbi->monspecs.modedb_len; i++) { /*FIXME now we do not support interlaced mode */ mode = &sii902x.fbi->monspecs.modedb[i]; if (!(mode->vmode & FB_VMODE_INTERLACED)) { dev_dbg(&sii902x.pdev->dev, "Added mode %d:", i); dev_dbg(&sii902x.pdev->dev, "xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n", mode->xres, mode->yres, mode->refresh, mode->vmode, mode->flag); fb_add_videomode(mode, &sii902x.fbi->modelist); } } fb_var_to_videomode(&m, &sii902x.fbi->var); dump_fb_videomode(&m); mode = fb_find_nearest_mode(&m, &sii902x.fbi->modelist); fb_videomode_to_var(&sii902x.fbi->var, mode); sii902x.fbi->var.activate |= FB_ACTIVATE_FORCE; console_lock(); sii902x.fbi->flags |= FBINFO_MISC_USEREVENT; fb_set_var(sii902x.fbi, &sii902x.fbi->var); sii902x.fbi->flags &= ~FBINFO_MISC_USEREVENT; console_unlock(); } /* Power on sii902x */ sii902x_poweron(); } } else { sii902x.cable_plugin = 0; dev_dbg(&sii902x.pdev->dev, "EVENT=plugout\n"); sprintf(event_string, "EVENT=plugout"); /* Power off sii902x */ sii902x_poweroff(); } kobject_uevent_env(&sii902x.pdev->dev.kobj, KOBJ_CHANGE, envp); } i2c_smbus_write_byte_data(sii902x.client, 0x3D, dat); dev_dbg(&sii902x.pdev->dev, "exit %s\n", __func__); }
static int tve_probe(struct platform_device *pdev) { int ret, i; struct resource *res; struct tve_platform_data *plat_data = pdev->dev.platform_data; u32 conf_reg; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) return -ENOMEM; tve.pdev = pdev; tve.base = ioremap(res->start, res->end - res->start); tve.irq = platform_get_irq(pdev, 0); if (tve.irq < 0) { ret = tve.irq; goto err0; } INIT_DELAYED_WORK(&tve.cd_work, cd_work_func); ret = request_irq(tve.irq, tve_detect_handler, 0, pdev->name, pdev); if (ret < 0) goto err0; ret = device_create_file(&pdev->dev, &dev_attr_headphone); if (ret < 0) goto err1; for (i = 0; i < num_registered_fb; i++) { if (strcmp(registered_fb[i]->fix.id, "DISP3 BG - DI1") == 0) { tve_fbi = registered_fb[i]; break; } } /* adjust video mode for mx37 */ if (cpu_is_mx37()) { video_modes[0].left_margin = 121; video_modes[0].right_margin = 16; video_modes[0].upper_margin = 17; video_modes[0].lower_margin = 5; video_modes[1].left_margin = 131; video_modes[1].right_margin = 12; video_modes[1].upper_margin = 21; video_modes[1].lower_margin = 3; } if (tve_fbi != NULL) { fb_add_videomode(&video_modes[0], &tve_fbi->modelist); fb_add_videomode(&video_modes[1], &tve_fbi->modelist); } tve.dac_reg = regulator_get(&pdev->dev, plat_data->dac_reg); if (!IS_ERR(tve.dac_reg)) { regulator_set_voltage(tve.dac_reg, 2500000); regulator_enable(tve.dac_reg); } tve.dig_reg = regulator_get(&pdev->dev, plat_data->dig_reg); if (!IS_ERR(tve.dig_reg)) { regulator_set_voltage(tve.dig_reg, 1250000); regulator_enable(tve.dig_reg); } tve.clk = clk_get(&pdev->dev, "tve_clk"); clk_set_rate(tve.clk, 216000000); clk_enable(tve.clk); if (_tve_get_revision() == 1) { tve_regs = &tve_regs_v1; tve_reg_fields = &tve_reg_fields_v1; } else { tve_regs = &tve_regs_v2; tve_reg_fields = &tve_reg_fields_v2; } /* Setup cable detect, for YPrPb mode, default use channel#0 for Y */ __raw_writel(0x01067701, tve.base + tve_regs->tve_cd_cont_reg); /* tve_man_detect(); not working */ conf_reg = 0; __raw_writel(conf_reg, tve.base + tve_regs->tve_com_conf_reg); __raw_writel(0x00000000, tve.base + tve_regs->tve_mv_cont_reg - 4 * 5); __raw_writel(0x00000000, tve.base + tve_regs->tve_mv_cont_reg - 4 * 4); __raw_writel(0x00000000, tve.base + tve_regs->tve_mv_cont_reg - 4 * 3); __raw_writel(0x00000000, tve.base + tve_regs->tve_mv_cont_reg - 4 * 2); __raw_writel(0x00000000, tve.base + tve_regs->tve_mv_cont_reg - 4); __raw_writel(0x00000000, tve.base + tve_regs->tve_mv_cont_reg); clk_disable(tve.clk); ret = fb_register_client(&nb); if (ret < 0) goto err2; return 0; err2: device_remove_file(&pdev->dev, &dev_attr_headphone); err1: free_irq(tve.irq, pdev); err0: iounmap(tve.base); 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; }
static int mxc_elcdif_fb_probe(struct platform_device *pdev) { int ret = 0; struct mxc_elcdif_fb_data *data; struct resource *res; struct fb_info *fbi; struct mxc_fb_platform_data *pdata = pdev->dev.platform_data; const struct fb_videomode *mode; struct fb_videomode m; int num; fbi = framebuffer_alloc(sizeof(struct mxc_elcdif_fb_data), &pdev->dev); if (fbi == NULL) { ret = -ENOMEM; goto out; } data = (struct mxc_elcdif_fb_data *)fbi->par; data->cur_blank = data->next_blank = FB_BLANK_UNBLANK; fbi->var.activate = FB_ACTIVATE_NOW; fbi->fbops = &mxc_elcdif_fb_ops; fbi->flags = FBINFO_FLAG_DEFAULT; fbi->pseudo_palette = data->pseudo_palette; ret = fb_alloc_cmap(&fbi->cmap, 16, 0); if (ret) goto out; g_elcdif_dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { dev_err(&pdev->dev, "cannot get IRQ resource\n"); ret = -ENODEV; goto err0; } data->dma_irq = res->start; ret = request_irq(data->dma_irq, lcd_irq_handler, 0, "mxc_elcdif_fb", data); if (ret) { dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n", data->dma_irq, ret); goto err0; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { ret = -ENODEV; goto err1; } elcdif_base = ioremap(res->start, SZ_4K); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res) { fbi->fix.smem_len = res->end - res->start + 1; fbi->fix.smem_start = res->start; fbi->screen_base = ioremap(fbi->fix.smem_start, fbi->fix.smem_len); } strcpy(fbi->fix.id, "mxc_elcdif_fb"); fbi->var.xres = 800; fbi->var.yres = 480; if (pdata && !data->output_pix_fmt) data->output_pix_fmt = pdata->interface_pix_fmt; INIT_LIST_HEAD(&fbi->modelist); if (pdata && pdata->mode && pdata->num_modes) fb_videomode_to_modelist(pdata->mode, pdata->num_modes, &fbi->modelist); if (mxc_disp_mode.num_modes) { int i; mode = mxc_disp_mode.mode; num = mxc_disp_mode.num_modes; for (i = 0; i < num; i++) { /* * FIXME now we do not support interlaced * mode for ddc mode */ if ((mxc_disp_mode.dev_mode & MXC_DISP_DDC_DEV) && (mode[i].vmode & FB_VMODE_INTERLACED)) continue; else { dev_dbg(&pdev->dev, "Added mode %d:", i); dev_dbg(&pdev->dev, "xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n", mode[i].xres, mode[i].yres, mode[i].refresh, mode[i].vmode, mode[i].flag); fb_add_videomode(&mode[i], &fbi->modelist); } } } if (!fb_mode && pdata && pdata->mode_str) fb_mode = pdata->mode_str; if (fb_mode) { dev_dbg(&pdev->dev, "default video mode %s\n", fb_mode); ret = fb_find_mode(&fbi->var, fbi, fb_mode, NULL, 0, NULL, default_bpp); if ((ret == 1) || (ret == 2)) { fb_var_to_videomode(&m, &fbi->var); dump_fb_videomode(&m); mode = fb_find_nearest_mode(&m, &fbi->modelist); fb_videomode_to_var(&fbi->var, mode); } else if (pdata && pdata->mode && pdata->num_modes) { ret = fb_find_mode(&fbi->var, fbi, fb_mode, pdata->mode, pdata->num_modes, NULL, default_bpp); if (!ret) { dev_err(fbi->device, "No valid video mode found"); goto err2; } } else { dev_err(fbi->device, "No valid video mode found"); goto err2; } } mxc_elcdif_fb_check_var(&fbi->var, fbi); fbi->var.xres_virtual = fbi->var.xres; fbi->var.yres_virtual = fbi->var.yres * 3; mxc_elcdif_fb_set_fix(fbi); if (!res || !res->end) if (mxc_elcdif_fb_map_video_memory(fbi) < 0) { ret = -ENOMEM; goto err2; } g_elcdif_axi_clk = clk_get(g_elcdif_dev, "elcdif_axi"); if (g_elcdif_axi_clk == NULL) { dev_err(&pdev->dev, "can't get ELCDIF axi clk\n"); ret = -ENODEV; goto err3; } g_elcdif_pix_clk = clk_get(g_elcdif_dev, "elcdif_pix"); if (g_elcdif_pix_clk == NULL) { dev_err(&pdev->dev, "can't get ELCDIF pix clk\n"); ret = -ENODEV; goto err3; } /* * Set an appropriate pixel clk rate first, so that we can * access ELCDIF registers. */ clk_set_rate(g_elcdif_pix_clk, 25000000); fbi->var.activate |= FB_ACTIVATE_FORCE; console_lock(); fbi->flags |= FBINFO_MISC_USEREVENT; ret = fb_set_var(fbi, &fbi->var); fbi->flags &= ~FBINFO_MISC_USEREVENT; console_unlock(); if (data->cur_blank == FB_BLANK_UNBLANK) { console_lock(); fb_blank(fbi, FB_BLANK_UNBLANK); console_unlock(); } ret = register_framebuffer(fbi); if (ret) goto err3; platform_set_drvdata(pdev, fbi); return 0; err3: mxc_elcdif_fb_unmap_video_memory(fbi); err2: iounmap(elcdif_base); err1: free_irq(data->dma_irq, data); err0: fb_dealloc_cmap(&fbi->cmap); framebuffer_release(fbi); out: return ret; }
static int adv739x_disp_init(struct mxc_dispdrv_handle *disp, struct mxc_dispdrv_setting *setting) { int ret = 0, i; struct adv739x_data *adv739x = mxc_dispdrv_getdata(disp); struct fsl_mxc_lcd_platform_data *plat = adv739x->client->dev.platform_data; struct fb_videomode *modedb = adv739x_modedb; int modedb_sz = adv739x_modedb_sz; static bool inited = false; if (inited) return -EBUSY; inited = true; setting->dev_id = plat->ipu_id; setting->disp_id = plat->disp_id; { struct clk *di_parent; struct clk *di; char di_clk[] = "ipu1_di0_clk"; di_clk[3] += setting->dev_id; di_clk[7] += setting->disp_id; di = clk_get(NULL, di_clk); if (IS_ERR(di)) { pr_err("%s: clock %s not found\n", __func__, di_clk); } di_parent = clk_get(NULL, "pll3_pfd_540M"); if (IS_ERR(di_parent)) { pr_err("%s: clock pll3_pfd_540M not found\n", __func__); } clk_set_parent(di, di_parent); clk_set_rate(di, 540000000/5); clk_enable(di_parent); } 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->default_ifmt; adv739x->ifmt = plat->default_ifmt; } INIT_LIST_HEAD(&setting->fbi->modelist); for (i = 0; i < modedb_sz; i++) { fb_add_videomode(&modedb[i], &setting->fbi->modelist); } adv739x->fbi = setting->fbi; adv739x->enabled = 0; adv739x->cur_mode = ADV739X_MODE_NTSC; //default mode adv739x->pdev = platform_device_register_simple("mxc_adv739x", 0, NULL, 0); if (IS_ERR(adv739x->pdev)) { dev_err(&adv739x->client->dev, "Unable to register adv739x as a platform device\n"); ret = PTR_ERR(adv739x->pdev); goto register_pltdev_failed; } /* Claim pins */ if (plat->get_pins) if (!plat->get_pins()) { ret = -EACCES; goto get_pins_failed; } adv739x->nb.notifier_call = adv739x_fb_event; ret = fb_register_client(&adv739x->nb); if (ret < 0) goto reg_fbclient_failed; return ret; reg_fbclient_failed: get_pins_failed: platform_device_unregister(adv739x->pdev); register_pltdev_failed: return ret; }
static int rk3036_tve_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct resource *res; const struct of_device_id *match; int i; int val = 0; match = of_match_node(rk3036_tve_dt_ids, np); if (!match) return PTR_ERR(match); rk3036_tve = devm_kzalloc(&pdev->dev, sizeof(struct rk3036_tve), GFP_KERNEL); if (!rk3036_tve) { dev_err(&pdev->dev, "rk3036 tv encoder device kmalloc fail!"); return -ENOMEM; } if (of_property_read_u32(np, "test_mode", &val)) rk3036_tve->test_mode = 0; else rk3036_tve->test_mode = val; if (!strcmp(match->compatible, "rockchip,rk3036-tve")) { rk3036_tve->soctype = SOC_RK3036; rk3036_tve->inputformat = INPUT_FORMAT_RGB; } else if (!strcmp(match->compatible, "rockchip,rk312x-tve")) { rk3036_tve->soctype = SOC_RK312X; rk3036_tve->inputformat = INPUT_FORMAT_YUV; } else { dev_err(&pdev->dev, "It is not a valid tv encoder!"); kfree(rk3036_tve); return -ENOMEM; } platform_set_drvdata(pdev, rk3036_tve); rk3036_tve->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); rk3036_tve->reg_phy_base = res->start; rk3036_tve->len = resource_size(res); rk3036_tve->regbase = ioremap(res->start, rk3036_tve->len); if (IS_ERR(rk3036_tve->regbase)) { dev_err(&pdev->dev, "rk3036 tv encoder device map registers failed!"); return PTR_ERR(rk3036_tve->regbase); } INIT_LIST_HEAD(&(rk3036_tve->modelist)); for (i = 0; i < ARRAY_SIZE(rk3036_cvbs_mode); i++) fb_add_videomode(&rk3036_cvbs_mode[i], &(rk3036_tve->modelist)); if (cvbsformat >= 0) { rk3036_tve->mode = (struct fb_videomode *)&rk3036_cvbs_mode[cvbsformat]; rk3036_tve->enable = 1; tve_switch_fb(rk3036_tve->mode, 1); } else { rk3036_tve->mode = (struct fb_videomode *)&rk3036_cvbs_mode[1]; } rk3036_tve->ddev = rk_display_device_register(&display_cvbs, &pdev->dev, NULL); rk_display_device_enable(rk3036_tve->ddev); fb_register_client(&tve_fb_notifier); cvbsformat = -1; dev_info(&pdev->dev, "%s tv encoder probe ok\n", match->compatible); return 0; }
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; }
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; }