Exemplo n.º 1
0
static int __devinit milkymistfb_probe(struct platform_device *pdev)
{
	struct milkymistfb *milkymistfb;
	struct fb_info *info;
	int ret = -ENOMEM;

	info = framebuffer_alloc(sizeof(*milkymistfb), &pdev->dev);
	if (!info)
		return -ENOMEM;

	info->fbops = &milkymistfb_ops;
	milkymistfb = info->par;
	milkymistfb->fb = info;

	fb_find_mode(&info->var, info, milkymistfb_mode_option,
		milkymist_modedb, ARRAY_SIZE(milkymist_modedb), NULL, 16);

/*	milkymistfb->vidmem = dma_alloc_coherent(&pdev->dev, videomemorysize,
		&milkymistfb->vidmem_phys, GFP_KERNEL);*/
	milkymistfb->vidmem = vmalloc(videomemorysize);
	milkymistfb->vidmem_phys = (unsigned int)milkymistfb->vidmem;
	if (!milkymistfb->vidmem) {
		ret = -ENOMEM;
		goto err_framebuffer_release;
	}
	memset(milkymistfb->vidmem, 0, videomemorysize);

	info->screen_base = milkymistfb->vidmem;
	info->fix = milkymistfb_fix;
	info->pseudo_palette = milkymistfb->pseudo_palette;
	info->flags = FBINFO_FLAG_DEFAULT;
	info->fix.smem_start = milkymistfb->vidmem_phys;
	info->fix.smem_len = videomemorysize;

	ret = fb_alloc_cmap(&info->cmap, 256, 0);
	if (ret < 0)
		goto err_dma_free;

	ret = register_framebuffer(info);
	if (ret < 0)
		goto err_dealloc_cmap;

	platform_set_drvdata(pdev, milkymistfb);

	dev_info(&pdev->dev,
	       "fb%d: Milkymist frame buffer at %p, size %ld k\n",
	       info->node, milkymistfb->vidmem, videomemorysize >> 10);

	return 0;

err_dealloc_cmap:
	fb_dealloc_cmap(&info->cmap);
err_dma_free:
/*	dma_free_coherent(&pdev->dev, videomemorysize, milkymistfb->vidmem,
		milkymistfb->vidmem_phys);*/
	vfree(milkymistfb->vidmem);
err_framebuffer_release:
	framebuffer_release(info);
	return ret;
}
Exemplo n.º 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;
}
Exemplo n.º 3
0
int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
			 const char *mode_option, unsigned int default_bpp)
{
    const struct fb_videomode *db = NULL;
    unsigned int dbsize = 0;

    if (mode_option && !strncmp(mode_option, "mac", 3)) {
	db = mac_modedb;
	dbsize = sizeof(mac_modedb)/sizeof(*mac_modedb);
    }
    return fb_find_mode(var, info, mode_option, db, dbsize,
			&mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);
}
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;
}
Exemplo n.º 5
0
/*!
 * @brief Install framebuffer into the system.
 *
 * @param info	framebuffer information pointer
 * @param pdev  pointer to struct device
 * @return	Negative errno on error, or zero on success.
 */
static int __init _install_fb(struct fb_info *info,
			      struct platform_device *pdev)
{
	struct mx2fb_info *mx2fbi = (struct mx2fb_info *)info->par;

	if (_init_fbinfo(info, pdev))
		return -EINVAL;

	if (fb_mode == 0)
		fb_mode = pdev->dev.platform_data;

	if (!fb_find_mode(&info->var, info, fb_mode, mxcfb_modedb,
			  mxcfb_modedb_sz, NULL, default_bpp)) {
		fb_dealloc_cmap(&info->cmap);
		return -EBUSY;
	}

	/* Default Y virtual size is 2x panel size */
	/* info->var.yres_virtual = info->var.yres << 1; */

	if (mx2fbi->type == MX2FB_TYPE_GW)
		mx2fbi->blank = FB_BLANK_NORMAL;
	else
		mx2fbi->blank = FB_BLANK_UNBLANK;

	if (mx2fb_set_par(info)) {
		fb_dealloc_cmap(&info->cmap);
		return -EINVAL;
	}

	if (register_framebuffer(info) < 0) {
		_unmap_video_memory(info);
		fb_dealloc_cmap(&info->cmap);
		return -EINVAL;
	}

	mx2fbi->registered = 1;
	dev_info(info->device, "fb%d: %s fb device registered successfully.\n",
		 info->node, info->fix.id);

	return 0;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
static int __init vfb_probe(struct platform_device *dev)
{
	struct fb_info *info;
	int retval = -ENOMEM;

	/* Reserve the framebuffer memory */
	if (!request_mem_region(vfb_addr, vfb_size, "STM32F4 Framebuffer")) {
		printk(KERN_ERR "vfb: unable to reserve "
		       "framebuffer at 0x%0x\n", (unsigned int)vfb_addr);
		retval = -EBUSY;
		goto fail_reqmem;
	}

	/* Allocate framebuffer info structure */
	info = framebuffer_alloc(sizeof(struct fb_info), &dev->dev);
	if (!info) {
		printk(KERN_ERR "vfb: unable to reserve framebuffer info\n");
		retval = -ENOMEM;
		goto fail_fballoc;
	}

	/* For real video cards we use ioremap */
	info->screen_base = ioremap(vfb_addr, vfb_size);
	if (!info->screen_base) {
		printk(KERN_ERR "vfb: unable to map framebuffer\n");
		retval = -ENOMEM;
		goto fail_remap;
	}

	/* Assign the frame buffer data */
	info->screen_size = vfb_size;
	info->fbops = &vfb_ops;

	/*
	 * VFB must clear memory to prevent kernel info
	 * leakage into userspace
	 * VGA-based drivers MUST NOT clear memory if
	 * they want to be able to take over vgacon
	 */
	memset(info->screen_base, 0, info->screen_size);

	retval = fb_find_mode(&info->var, info, NULL, NULL, 0, NULL, 8);
	if ((!retval) || (retval == 4))
		memcpy(&(info->var), &vfb_default,
		       sizeof(struct fb_var_screeninfo));

	vfb_fix.smem_start = vfb_addr;
	vfb_fix.smem_len = vfb_size;
	memcpy(&(info->fix), &vfb_fix, sizeof(struct fb_fix_screeninfo));

	/* Allocate pseudo palette data */
	info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
	if (!info->pseudo_palette) {
		printk(KERN_ERR "vfb: unable to reserve palette memory\n");
		retval = -ENOMEM;
		goto fail_palette;
	}
	//info->pseudo_palette = info->par;
	info->par = NULL;
	info->flags = FBINFO_FLAG_DEFAULT;

	/*
	 * We expect the boot loader to have initialized the chip
	 * with appropriate parameters from which we can determinte
	 * the flavor of lcd panel attached
	 */
	retval = init_vals(info);
	if (retval < 0) {
		printk(KERN_ERR "vfb: unable to reserve cmap memory\n");
		goto fail_cmap;
	}

	/* Regiser the framebuffer */
	retval = register_framebuffer(info);
	if (retval < 0) {
		printk(KERN_ERR "vfb: unable to register framebuffer\n");
		goto fail_register;
	}

	/* Assign the driver data */
	platform_set_drvdata(dev, info);

	/* Everything is OK */
	printk(KERN_INFO
	       "fb%d: Virtual frame buffer device, "
	       "using %ldK of video memory\n",
	       info->node, info->screen_size >> 10);

	return 0;

	/* There is an error! */
fail_register:
	fb_dealloc_cmap(&info->cmap);
fail_cmap:
	kfree(info->pseudo_palette);
fail_palette:
	iounmap(info->screen_base);
fail_remap:
	framebuffer_release(info);
fail_fballoc:
	release_mem_region(vfb_addr, vfb_size);
fail_reqmem:

	return retval;
}
Exemplo n.º 8
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;

	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;

	if (pdata && pdata->mode && pdata->num_modes)
		fb_videomode_to_modelist(pdata->mode, pdata->num_modes,
				&fbi->modelist);

	if (!fb_mode && pdata && pdata->mode_str)
		fb_mode = pdata->mode_str;

	if (fb_mode) {
		ret = fb_find_mode(&fbi->var, fbi, fb_mode, NULL, 0, NULL,
				   default_bpp);
		if ((!ret || (ret > 2)) && pdata && pdata->mode &&
		    pdata->num_modes)
			fb_find_mode(&fbi->var, fbi, fb_mode, pdata->mode,
					pdata->num_modes, NULL, default_bpp);
	}

	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);

	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;
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
0
/*!
 * @brief Ioctl function to support customized ioctl operations.
 *
 * @param info	Framebuffer structure that represents a single frame buffer
 * @param cmd	The command number
 * @param arg	Argument which depends on cmd
 *
 * @return	Negative errno on error, or zero on success.
 */
static int mx2fb_ioctl(struct fb_info *info, unsigned int cmd,
		       unsigned long arg)
{
	struct mx2fb_info *mx2fbi = (struct mx2fb_info *)info->par;
	struct mx2fb_gbl_alpha ga;
	struct mx2fb_color_key ck;

	switch (cmd) {
	case MX2FB_SET_GBL_ALPHA:
		if (mx2fbi->type != MX2FB_TYPE_GW)
			return -ENODEV;

		if (!arg)
			return -EINVAL;

		/* set graphic window information */
		if (copy_from_user((void *)&ga, (void *)arg, sizeof(ga)))
			return -EFAULT;

		g_gwinfo.alpha_value = ga.alpha;

		if (g_gwinfo.enabled)
			_enable_graphic_window(info);
		else
			_disable_graphic_window(info);
		break;
	case MX2FB_SET_CLR_KEY:
		if (mx2fbi->type != MX2FB_TYPE_GW)
			return -ENODEV;

		if (!arg)
			return -EINVAL;

		/* set graphic window information */
		if (copy_from_user((void *)&ck, (void *)arg, sizeof(ck)))
			return -EFAULT;

		g_gwinfo.ck_enabled = ck.enable;
		g_gwinfo.ck_red = (ck.color_key & 0x003F0000) >> 16;
		g_gwinfo.ck_green = (ck.color_key & 0x00003F00) >> 8;
		g_gwinfo.ck_blue = ck.color_key & 0x0000003F;

		if (g_gwinfo.enabled)
			_enable_graphic_window(info);
		else
			_disable_graphic_window(info);
		break;
	case FBIOGET_GWINFO:
		if (mx2fbi->type != MX2FB_TYPE_GW)
			return -ENODEV;

		if (!arg)
			return -EINVAL;

		/* get graphic window information */
		if (copy_to_user((void *)arg, (void *)&g_gwinfo,
				 sizeof(g_gwinfo)))
			return -EFAULT;
		break;
	case FBIOPUT_GWINFO:
		if (mx2fbi->type != MX2FB_TYPE_GW)
			return -ENODEV;

		if (!arg)
			return -EINVAL;

		/* set graphic window information */
		if (copy_from_user((void *)&g_gwinfo, (void *)arg,
				   sizeof(g_gwinfo)))
			return -EFAULT;

		if (g_gwinfo.enabled)
			_enable_graphic_window(info);
		else
			_disable_graphic_window(info);
		break;
#ifdef CONFIG_FB_MXC_TVOUT
	case ENCODER_GET_CAPABILITIES:{
			int ret;
			struct video_encoder_capability cap;

			if (mx2fbi->type != MX2FB_TYPE_BG)
				return -ENODEV;

			ret = fs453_ioctl(cmd, &cap);
			if (ret)
				return ret;

			if (copy_to_user((void *)arg, &cap, sizeof(cap)))
				return -EFAULT;
			break;
		}
	case ENCODER_SET_NORM:{
			int ret;
			unsigned long mode;
			char *smode;
			struct fb_var_screeninfo var;

			if (mx2fbi->type != MX2FB_TYPE_BG)
				return -ENODEV;

			if (copy_from_user(&mode, (void *)arg, sizeof(mode)))
				return -EFAULT;
			if ((ret = fs453_ioctl(cmd, &mode)))
				return ret;

			if (mode == VIDEO_ENCODER_PAL)
				smode = MODE_PAL;
			else if (mode == VIDEO_ENCODER_NTSC)
				smode = MODE_NTSC;
			else
				smode = MODE_VGA;

			var = info->var;
			var.nonstd = 0;
			ret = fb_find_mode(&var, info, smode, mxcfb_modedb,
					   mxcfb_modedb_sz, NULL, default_bpp);
			if ((ret != 1) && (ret != 2))	/* specified mode not found */
				return -ENODEV;

			info->var = var;
			fb_mode = smode;
			return mx2fb_set_par(info);
		}
	case ENCODER_SET_INPUT:
	case ENCODER_SET_OUTPUT:
	case ENCODER_ENABLE_OUTPUT:{
			unsigned long varg;

			if (mx2fbi->type != MX2FB_TYPE_BG)
				return -ENODEV;

			if (copy_from_user(&varg, (void *)arg, sizeof(varg)))
				return -EFAULT;
			return fs453_ioctl(cmd, &varg);
		}
#endif
	default:
		dev_dbg(info->device, "Unknown ioctl command (0x%08X)\n", cmd);
		return -EINVAL;
	}

	return 0;
}
Exemplo n.º 11
0
/************************************************************************
 *  Initialization and cleanup code
 */
static int stmfb_parse_module_parameters(struct stmfb_info *i, int display)
{
  char *paramstring    = NULL;
  char *copy           = NULL;
  char *mode           = NULL;
  char *memsize        = NULL;
  char *auxmemsize     = NULL;
  char *tvstandard     = NULL;
  char *componentvideo = NULL;
  char *hdmivideo      = NULL;
  char *blit_api_ver;
  unsigned long fbsize = 0;
  int stride;


  /*
   * Note: slightly messy due to module parameter limitations and not wanting to
   * use parameter arrays.
   */
  switch(display)
  {
    case 0:
      paramstring = display0;
      break;
    case 1:
      paramstring = display1;
      break;
    case 2:
      paramstring = display2;
      break;
    case 3:
      paramstring = display3;
      break;
    default:
      break;
  }

  printk("stmfb: fb%d parameters = \"%s\"\n",display,(paramstring==NULL)?"<NULL>":paramstring);

  if(paramstring == NULL || *paramstring == '\0')
    return -ENODEV;

  copy = kstrdup(paramstring, GFP_KERNEL);
  if(!copy)
    return -ENOMEM;

  mode           = strsep(&copy,":,");
  memsize        = strsep(&copy,":,");
  auxmemsize     = strsep(&copy,":,");
  tvstandard     = strsep(&copy,":,");
  componentvideo = strsep(&copy,":,");
  hdmivideo      = strsep(&copy,":,");
  blit_api_ver   = strsep(&copy,":,");

  if(!mode || *mode == '\0')
  {
    DPRINTK("No mode string found\n");
    kfree(copy);
    return -ENODEV;
  }

  if(fb_find_mode(&i->info.var,&i->info,mode,i->videomodedb,ARRAY_SIZE(i->videomodedb),NULL,16) == 0)
  {
    DPRINTK("No suitable mode found (not even a default!)\n");
    kfree(copy);
    return -ENODEV;
  }

  if(memsize)
  {
    fbsize = (unsigned long)memparse(memsize,&memsize);
    DPRINTK("requested memory = %lu\n",fbsize);
  }

  stride = i->info.var.xres * (i->info.var.bits_per_pixel/8);
  i->info.var.yres_virtual  = fbsize / stride;

  if(i->info.var.yres_virtual < i->info.var.yres)
  {
    DPRINTK("Requested memory is too small for default video mode, fixing it\n");
    fbsize = i->info.var.yres * stride;
  }

  /*
   * Having determined size, set the virtual yres to equal yres for the
   * default mode.
   */
  i->info.var.yres_virtual = i->info.var.yres;

  i->ulFBSize = fbsize;

  if(auxmemsize)
  {
    i->AuxSize[0] = (unsigned long)memparse(auxmemsize,&auxmemsize);
    DPRINTK("requested %lu bytes of auxiliary memory\n",i->AuxSize[0]);
  }
  else
    i->AuxSize[0] = 0;

  i->default_sd_encoding = STM_OUTPUT_STD_NTSC_M;

  if (tvstandard)
  {
    switch(*tvstandard)
    {
      case 'N':
      case 'n':
      {
        if(!strcmp(tvstandard,"NTSC-J"))
        {
          DPRINTK("Selecting NTSC-J output\n");
          i->default_sd_encoding = STM_OUTPUT_STD_NTSC_J;
        }
        else if(!strcmp(tvstandard,"NTSC-443"))
        {
          DPRINTK("Selecting NTSC-443 output\n");
          i->default_sd_encoding = STM_OUTPUT_STD_NTSC_443;
        }
        else
        {
          DPRINTK("Selecting NTSC (US) output\n");
          i->default_sd_encoding = STM_OUTPUT_STD_NTSC_M;
        }
        break;
      }
      case 'S':
      case 's':
      {
        DPRINTK("Selecting SECAM output\n");
        i->default_sd_encoding = STM_OUTPUT_STD_SECAM;
        break;
      }
      case 'P':
      case 'p':
      {
        if(!strcmp(tvstandard,"PAL-M"))
        {
          DPRINTK("Selecting PAL-M output\n");
          i->default_sd_encoding = STM_OUTPUT_STD_PAL_M;
        }
        else if(!strcmp(tvstandard,"PAL-N"))
        {
          DPRINTK("Selecting PAL-N output\n");
          i->default_sd_encoding = STM_OUTPUT_STD_PAL_N;
        }
        else if(!strcmp(tvstandard,"PAL-Nc"))
        {
          DPRINTK("Selecting PAL-Nc output\n");
          i->default_sd_encoding = STM_OUTPUT_STD_PAL_Nc;
        }
        else if(!strcmp(tvstandard, "PAL-60"))
        {
          DPRINTK("Selecting PAL-60 output\n");
          i->default_sd_encoding = STM_OUTPUT_STD_PAL_60;
        }
        else
        {
          DPRINTK("Selecting PAL-BDGHI output\n");
          i->default_sd_encoding = STM_OUTPUT_STD_PAL_BDGHI;
        }

        break;
      }
      default:
      {
        DPRINTK("Invalid default SD output standard, falling back to NTSC\n");
      }
    }
  }

  if(i->main_config.caps & STMFBIO_OUTPUT_CAPS_SDTV_ENCODING)
    i->main_config.sdtv_encoding = i->default_sd_encoding;

  /*
   * Set the output format
   */
  if(componentvideo)
  {
    ULONG outputcaps;
    if(stm_display_output_get_capabilities(i->pFBMainOutput,&outputcaps)<0)
    {
      DPRINTK("Cannot get output capabilities\n");
      return -EIO;
    }

    switch(*componentvideo)
    {
      case 'C':
      case 'c':
        if(outputcaps & (STM_OUTPUT_CAPS_CVBS_YC_EXCLUSIVE |
                         STM_OUTPUT_CAPS_SD_RGB_CVBS_YC    |
                         STM_OUTPUT_CAPS_SD_YPrPb_CVBS_YC))
        {
          i->main_config.analogue_config = STMFBIO_OUTPUT_ANALOGUE_CVBS;
          i->main_config.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_YC;
        }
        else
        {
          printk(KERN_WARNING "Cannot select CVBS/S-Video on display %d\n",display);
        }
        break;
      case 'R':
      case 'r':
        if(outputcaps & (STM_OUTPUT_CAPS_RGB_EXCLUSIVE |
                         STM_OUTPUT_CAPS_SD_RGB_CVBS_YC))
        {
          i->main_config.analogue_config = STMFBIO_OUTPUT_ANALOGUE_RGB;
          if(outputcaps & STM_OUTPUT_CAPS_SD_RGB_CVBS_YC)
            i->main_config.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_CVBS;
        }
        else
        {
          printk(KERN_WARNING "Cannot select RGB on display %d\n",display);
        }
        break;
      case 'Y':
      case 'y':
        if(outputcaps & (STM_OUTPUT_CAPS_YPrPb_EXCLUSIVE |
                         STM_OUTPUT_CAPS_SD_YPrPb_CVBS_YC))
        {
          i->main_config.analogue_config = STMFBIO_OUTPUT_ANALOGUE_YPrPb;

          if(outputcaps & STM_OUTPUT_CAPS_SD_YPrPb_CVBS_YC)
            i->main_config.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_CVBS;
        }
        else
        {
          printk(KERN_WARNING "Cannot select YPrPb on display %d\n",display);
        }
        break;
      default:
        printk(KERN_WARNING "Unknown analogue video type option - falling back to driver defaults\n");
        break;
    }
  }

  if(hdmivideo && i->hdmi)
  {
    switch(*hdmivideo)
    {
      case 'Y':
      case 'y':
        i->hdmi->video_type   = STM_VIDEO_OUT_YUV;
        i->main_config.hdmi_config |= STMFBIO_OUTPUT_HDMI_YUV;
        break;
      default:
        DPRINTK("Unknown hdmi video type option - falling back to RGB\n");
      case 'R':
      case 'r':
        i->hdmi->video_type   = STM_VIDEO_OUT_RGB;
        i->main_config.hdmi_config &= ~STMFBIO_OUTPUT_HDMI_YUV;
        break;
    }
  }

  i->blitter_api = 1;
  if (blit_api_ver)
  {
    if (blit_api_ver[0] >= '0' && blit_api_ver[0] <= '9'
        && blit_api_ver[1] == '\0')
      i->blitter_api = *blit_api_ver - '0';
    else
      printk(KERN_WARNING "Unknown Blitter API version specified, ignoring\n");
  }

  kfree(copy);

  return 0;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
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;
}