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;
}
Example #2
0
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);
}
Example #4
0
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;
}
Example #8
0
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;
}
Example #9
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;
}
Example #10
0
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__);

}
Example #12
0
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;
}
Example #13
0
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;
}
Example #14
0
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;
}
Example #15
0
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;
}
Example #17
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;
}
Example #18
0
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;
}