static OMAP_ERROR EnableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
{
	int                res;
	OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
	OMAP_ERROR         eError;

	
	memset(&psDevInfo->sLINNotifBlock, 0, sizeof(psDevInfo->sLINNotifBlock));

	psDevInfo->sLINNotifBlock.notifier_call = FrameBufferEvents;

	psSwapChain->bBlanked = OMAP_FALSE;

	res = fb_register_client(&psDevInfo->sLINNotifBlock);
	if (res != 0)
	{
		printk(KERN_WARNING DRIVER_PREFIX
			": fb_register_client failed (%d)", res);

		return (OMAP_ERROR_GENERIC);
	}

	eError = UnblankDisplay(psDevInfo);
	if (eError != OMAP_OK)
	{
		DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
			": UnblankDisplay failed (%d)", eError));
		return eError;
	}

	return (OMAP_OK);
}
Beispiel #2
0
static int __init am200_init(void)
{
	int ret;

	/* before anything else, we request notification for any fb
	 * creation events */
	fb_register_client(&am200_fb_notif);

	/* request our platform independent driver */
	request_module("metronomefb");

	am200_device = platform_device_alloc("metronomefb", -1);
	if (!am200_device)
		return -ENOMEM;

	/* the am200_board that will be seen by metronomefb is a copy */
	platform_device_add_data(am200_device, &am200_board,
					sizeof(am200_board));

	/* this _add binds metronomefb to am200. metronomefb refcounts am200 */
	ret = platform_device_add(am200_device);

	if (ret) {
		platform_device_put(am200_device);
		fb_unregister_client(&am200_fb_notif);
		return ret;
	}

	am200_presetup_fb();

	return 0;
}
int __init init_display_devices(void)
{
	int ret;

	ret = fb_register_client(&framebuffer_nb);
	if (ret)
		pr_warning("Failed to register framebuffer notifier\n");

	ret = mcde_dss_register_notifier(&display_nb);
	if (ret)
		pr_warning("Failed to register dss notifier\n");

#ifdef CONFIG_DISPLAY_GENERIC_PRIMARY
	if (display_initialized_during_boot)
		generic_display0.power_mode = MCDE_DISPLAY_PM_STANDBY;
	ret = mcde_display_device_register(&generic_display0);
	if (ret)
		pr_warning("Failed to register generic display device 0\n");
#endif

#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
	INIT_DELAYED_WORK_DEFERRABLE(&work_dispreg_hdmi,
			delayed_work_dispreg_hdmi);

	schedule_delayed_work(&work_dispreg_hdmi,
			msecs_to_jiffies(DISPREG_HDMI_DELAY));
#endif

	return ret;
}
static int __init ppm_lcmoff_policy_init(void)
{
	int ret = 0;

	FUNC_ENTER(FUNC_LV_POLICY);

#ifdef CONFIG_HAS_EARLYSUSPEND
	register_early_suspend(&ppm_lcmoff_es_handler);
#else
	if (fb_register_client(&ppm_lcmoff_fb_notifier)) {
		ppm_err("@%s: lcmoff policy register FB client failed!\n", __func__);
		ret = -EINVAL;
		goto out;
	}
#endif

	if (ppm_main_register_policy(&lcmoff_policy)) {
		ppm_err("@%s: lcmoff policy register failed\n", __func__);
		ret = -EINVAL;
		goto out;
	}

	ppm_info("@%s: register %s done!\n", __func__, lcmoff_policy.name);

out:
	FUNC_EXIT(FUNC_LV_POLICY);

	return ret;
}
Beispiel #5
0
int __init mdss_dsi_status_init(void)
{
	int rc = 0;

	pstatus_data = kzalloc(sizeof(struct dsi_status_data), GFP_KERNEL);
	if (!pstatus_data) {
		pr_err("%s: can't allocate memory\n", __func__);
		return -ENOMEM;
	}

	pstatus_data->fb_notifier.notifier_call = fb_event_callback;

	rc = fb_register_client(&pstatus_data->fb_notifier);
	if (rc < 0) {
		pr_err("%s: fb_register_client failed, returned with rc=%d\n",
								__func__, rc);
		kfree(pstatus_data);
		return -EPERM;
	}

	pstatus_data->check_interval = interval;
	pr_info("%s: DSI status check interval:%d\n", __func__,	interval);

	INIT_DELAYED_WORK(&pstatus_data->check_status, check_dsi_ctrl_status);

	pr_debug("%s: DSI ctrl status work queue initialized\n", __func__);

	return rc;
}
/*!
 * This function is called whenever the platform device is detected.
 *
 * @param	pdev	the platform device
 *
 * @return 	Returns 0 on SUCCESS and error on FAILURE.
 */
static int __devinit lcd_probe(struct platform_device *pdev)
{
	int i;
	struct mxc_lcd_platform_data *plat = pdev->dev.platform_data;

	if (plat) {
		if (plat->reset)
			plat->reset();

		io_reg = regulator_get(&pdev->dev, plat->io_reg);
		if (IS_ERR(io_reg))
			io_reg = NULL;
		core_reg = regulator_get(&pdev->dev, plat->core_reg);
		if (!IS_ERR(core_reg))
			regulator_set_voltage(io_reg, 1800000, 1800000);
		else
			core_reg = NULL;
	}

	for (i = 0; i < num_registered_fb; i++) {
		if (strcmp(registered_fb[i]->fix.id, "mxc_elcdif_fb") == 0) {
			lcd_init_fb(registered_fb[i]);
			fb_show_logo(registered_fb[i], 0);
			lcd_poweron();
		}
	}

	fb_register_client(&nb);

	plcd_dev = pdev;

	return 0;
}
Beispiel #7
0
static int __devinit ite661x_probe(struct i2c_client *client,
		const struct i2c_device_id *id)
{
	int ret;
	struct mxc_lcd_platform_data *plat = client->dev.platform_data;
	struct fb_info edid_fbi;

	if (plat->boot_enable &&
		!g_enable_hdmi)
		g_enable_hdmi = MXC_ENABLE;
	if (!g_enable_hdmi)
		g_enable_hdmi = MXC_DISABLE;

	if (g_enable_hdmi == MXC_DISABLE) {
		printk(KERN_WARNING "By setting, ITE driver will not be enabled\n");
		return -ENODEV;
	}

	ite661x.client = client;

	if (plat->reset) {
		ite661x_reset = plat->reset;
		ite661x_reset();
	}

	HDMITX_ChangeDisplayOption(HDMI_480p60, HDMI_RGB444) ;
	InitCAT6611(client);

	if (ite661x.client->irq) {
		ret = request_irq(ite661x.client->irq, ite661x_detect_handler,
				IRQF_TRIGGER_FALLING,
				"ite661x_det", &ite661x);
		if (ret < 0)
			dev_warn(&ite661x.client->dev,
				"ite661x: cound not request det irq %d\n",
				ite661x.client->irq);
		else {
			/*enable cable hot plug irq*/
			INIT_DELAYED_WORK(&(ite661x.det_work), det_worker);
		}
		ret = device_create_file(&ite661x.pdev->dev, &dev_attr_fb_name);
		if (ret < 0)
			dev_warn(&ite661x.client->dev,
				"ite661x: cound not create sys node for fb name\n");
		ret = device_create_file(&ite661x.pdev->dev, &dev_attr_cable_state);
		if (ret < 0)
			dev_warn(&ite661x.client->dev,
				"ite661x: cound not create sys node for cable state\n");
		ret = device_create_file(&ite661x.pdev->dev, &dev_attr_edid);
		if (ret < 0)
			dev_warn(&ite661x.client->dev,
				"ite661x: cound not create sys node for edid\n");
	}

	fb_register_client(&nb);

	return 0;
}
static void __init rk3288_init_suspend(void)
{
    printk("%s\n",__FUNCTION__);
    fb_register_client(&rk3288_pll_early_suspend_notifier);
    rockchip_suspend_init();       
    rkpm_pie_init();
    rk3288_suspend_init();
   rkpm_set_ops_pwr_dmns(rk_pm_soc_pd_suspend,rk_pm_soc_pd_resume);
}
Beispiel #9
0
static void gf_setup_fb_notifier(struct gf_dev *gf_dev)
{
	int rc = 0;

	gf_dev->fb_notifier.notifier_call = gf_fb_notifier_callback;

	rc = fb_register_client(&gf_dev->fb_notifier);
	if (rc)
		GF_LOG_ERROR("failed to register fb_notifier: %d\n", rc);
}
static int __init msm_sleeper_init(void)
{
	pr_info("msm-sleeper version %d.%d\n",
		 MSM_SLEEPER_MAJOR_VERSION,
		 MSM_SLEEPER_MINOR_VERSION);

	fb_register_client(&msm_sleeper_fb_notif);

	return 0;
}
static int __init cpu_iboost_init(void)
{
	struct boost_policy *b;
	int cpu, ret;

	boost_wq = alloc_workqueue("cpu_iboost_wq", WQ_HIGHPRI, 0);
	if (!boost_wq) {
		pr_err("Failed to allocate workqueue\n");
		ret = -EFAULT;
		goto err;
	}

	cpufreq_register_notifier(&cpu_do_boost_nb, CPUFREQ_POLICY_NOTIFIER);

	INIT_DELAYED_WORK(&fb_boost_work, fb_boost_fn);

	fb_register_client(&fb_boost_nb);

	for_each_possible_cpu(cpu) {
		b = &per_cpu(boost_info, cpu);
		b->cpu = cpu;
		INIT_DELAYED_WORK(&b->ib_restore_work, ib_restore_main);
		init_waitqueue_head(&b->sync_wq);
		atomic_set(&b->being_woken, 0);
		spin_lock_init(&b->lock);
		INIT_DELAYED_WORK(&b->mig_boost_rem, do_mig_boost_rem);
		b->thread = kthread_run(boost_mig_sync_thread, (void *)cpu,
					"boost_sync/%d", cpu);
		set_cpus_allowed(b->thread, *cpumask_of(cpu));
	}

	atomic_notifier_chain_register(&migration_notifier_head, &boost_migration_nb);

	INIT_WORK(&boost_work, ib_boost_main);

	ret = input_register_handler(&cpu_iboost_input_handler);
	if (ret) {
		pr_err("Failed to register input handler, err: %d\n", ret);
		goto err;
	}

	cpu_iboost_kobject = kobject_create_and_add("cpu_input_boost", kernel_kobj);
	if (!cpu_iboost_kobject) {
		pr_err("Failed to create kobject\n");
		goto err;
	}

	ret = sysfs_create_group(cpu_iboost_kobject, &cpu_iboost_attr_group);
	if (ret) {
		pr_err("Failed to create sysfs interface\n");
		kobject_put(cpu_iboost_kobject);
	}
err:
	return ret;
}
/* common functions */
void __init lge_add_lcd_devices(void)
{
	if(ebi2_tovis_panel_data.initialized)
		ebi2_tovis_power_save(1);

	fb_register_client(&jump_fb_event_notifier);

	platform_device_register(&ebi2_tovis_panel_device);
	msm_fb_add_devices();
	lge_add_gpio_i2c_device(jump_init_i2c_backlight);
}
Beispiel #13
0
void __init lge_add_lcd_devices(void)
{
        if(ebi2_tovis_panel_data.initialized)
		ebi2_tovis_power_save(1);

	fb_register_client(&e0eu_fb_event_notifier);    

	platform_add_devices(e0eu_panel_devices, ARRAY_SIZE(e0eu_panel_devices));
	msm_fb_add_devices();
	lge_add_gpio_i2c_device(msm7x27a_e0eu_init_i2c_backlight);
}
static void cyttsp4_setup_early_suspend(struct cyttsp4_mt_data *md)
{
	int retval = 0;
	struct device *dev = &md->ttsp->dev;

    	dev_dbg(dev, "%s\n", __func__);
	md->fb_notif.notifier_call = cyttsp4_mt_fb_notifier_callback;

	retval = fb_register_client(&md->fb_notif);
	if (retval)
		dev_err(&md->ttsp->dev,
			"Unable to register fb_notifier: %d\n", retval);
	return;
}
Beispiel #15
0
static int __init exynos_init_cpuidle(void)
{
	int ret;

	ret = exynos_idle_state_init(&exynos64_idle_cluster0_driver, &hmp_fast_cpu_mask);
	if (ret) {
		pr_err("fail exynos_idle_state_init(cluster 0) ret = %d\n", ret);
		return ret;
	}

	cpuidle_profile_state_init(&exynos64_idle_cluster0_driver);

	exynos64_idle_cluster0_driver.safe_state_index = IDLE_C1;
	exynos64_idle_cluster0_driver.cpumask = &hmp_fast_cpu_mask;
	ret = cpuidle_register(&exynos64_idle_cluster0_driver, NULL);

	if (ret) {
		pr_err("fast cpu cpuidle_register fail ret = %d\n", ret);
		return ret;
	}

	ret = exynos_idle_state_init(&exynos64_idle_cluster1_driver, &hmp_slow_cpu_mask);
	if (ret) {
		pr_err("fail exynos_idle_state_init(cluster 1) ret = %d\n", ret);
		return ret;
	}

	exynos64_idle_cluster1_driver.safe_state_index = IDLE_C1;
	exynos64_idle_cluster1_driver.cpumask = &hmp_slow_cpu_mask;
	ret = cpuidle_register(&exynos64_idle_cluster1_driver, NULL);

	if (ret) {
		pr_err("slow cpu cpuidle_register fail ret = %d\n", ret);
		return ret;
	}

	/* TODO : SKIP idle correlation */

	register_pm_notifier(&exynos_cpuidle_notifier);
	register_reboot_notifier(&exynos_cpuidle_reboot_nb);

#if defined(CONFIG_EXYNOS_MARCH_DYNAMIC_CPU_HOTPLUG)
	fb_register_client(&fb_block);
#endif

	pr_info("%s, finish initialization of cpuidle\n", __func__);

	return 0;
}
void __init msm_fb_add_devices(void)
{
	if (ebi2_tovis_panel_data.initialized)
		ebi2_tovis_power_save(1);

	fb_register_client(&v1_fb_event_notifier);
	platform_add_devices(msm_fb_devices, ARRAY_SIZE(msm_fb_devices));
	platform_add_devices(v1_panel_devices, ARRAY_SIZE(v1_panel_devices));
	msm_fb_register_device("mdp", &mdp_pdata);
#ifdef CONFIG_FB_MSM_EBI2
	msm_fb_register_device("ebi2", 0);
#endif

#if defined(CONFIG_BACKLIGHT_LGE_RT8966)
	msm7x27a_v1_init_backlight();
#endif
}
void __init msm_fb_add_devices(void)
{
	if(ebi2_tovis_panel_data.initialized)
		ebi2_tovis_power_save(1);

	fb_register_client(&v3eu_fb_event_notifier);
	platform_add_devices(msm_fb_devices, ARRAY_SIZE(msm_fb_devices));
	platform_add_devices(v3eu_panel_devices, ARRAY_SIZE(v3eu_panel_devices));
	msm_fb_register_device("mdp", &mdp_pdata);
	msm_fb_register_device("lcdc", 0);
#ifdef CONFIG_FB_MSM_EBI2
	msm_fb_register_device("ebi2", 0);
#endif
#ifdef CONFIG_FB_MSM_MIPI_DSI
	msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
#endif

	lge_add_gpio_i2c_device(msm7x27a_v3eu_init_i2c_backlight);
}
Beispiel #18
0
static int __devinit at91sam9x5_video_probe(struct platform_device *pdev)
{
	int ret = -ENOMEM;
	size_t i;
	struct at91sam9x5_video_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);

	if (!priv) {
		dev_err(&pdev->dev, "failed to allocate driver private data\n");
		goto err_alloc_priv;
	}

	priv->pdev = pdev;
	priv->fb_notifier.notifier_call = at91sam9x5_video_fb_event_notify;

	platform_set_drvdata(pdev, priv);

	spin_lock_init(&priv->lock);

	ret = fb_register_client(&priv->fb_notifier);
	if (ret) {
		dev_err(&pdev->dev, "failed to register fb client (%d)\n", ret);

		kfree(priv);
err_alloc_priv:

		return ret;
	}

	/* XXX: This is racy. If a new fb is registered then
	 * at91sam9x5_video_register is called twice. This should be solved
	 * somewhere in drivers/fb. priv->fbinfo is used to prevent multiple
	 * registration.
	 */

	for (i = 0; i < ARRAY_SIZE(registered_fb); ++i)
		if (registered_fb[i])
			at91sam9x5_video_register(priv, registered_fb[i]);

	return 0;
}
/*!
 * This function is called whenever the SPI slave device is detected.
 *
 * @param	spi	the SPI slave device
 *
 * @return 	Returns 0 on SUCCESS and error on FAILURE.
 */
static int __devinit lcd_spi_probe(struct spi_device *spi)
{
	int i;
	struct mxc_lcd_platform_data *plat = spi->dev.platform_data;
	lcd_spi = spi;
	
	lcd_24bpp_ioinit();
	
	if (plat) {
		io_reg = regulator_get(&spi->dev, plat->io_reg);
		if (!IS_ERR(io_reg)) {
			regulator_set_voltage(io_reg, 1800000);
			regulator_enable(io_reg);
		}
		core_reg = regulator_get(&spi->dev, plat->core_reg);
		if (!IS_ERR(core_reg)) {
			regulator_set_voltage(core_reg, 2800000);
			regulator_enable(core_reg);
		}

		lcd_reset = plat->reset;
		if (lcd_reset)
			lcd_reset();
	}
	
	lcd_spi_setup(lcd_spi);

	for (i = 0; i < num_registered_fb; i++) {
		if (strcmp(registered_fb[i]->fix.id, "DISP3 BG") == 0) {
			lcd_init_fb(registered_fb[i]);
			fb_show_logo(registered_fb[i], 0);
			lcd_poweron(); 
		}
	}

	fb_register_client(&nb);

	return 0;
}
/* Set up Linux Framebuffer event notification */
OMAPLFB_ERROR OMAPLFBEnableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
{
	int                res;
	OMAPLFB_ERROR         eError;

	/* Set up Linux Framebuffer event notification */
	memset(&psDevInfo->sLINNotifBlock, 0, sizeof(psDevInfo->sLINNotifBlock));

	psDevInfo->sLINNotifBlock.notifier_call = OMAPLFBFrameBufferEvents;

	OMAPLFBAtomicBoolSet(&psDevInfo->sBlanked, OMAPLFB_FALSE);
	OMAPLFBAtomicIntSet(&psDevInfo->sBlankEvents, 0);

	res = fb_register_client(&psDevInfo->sLINNotifBlock);
	if (res != 0)
	{
		printk(KERN_ERR DRIVER_PREFIX
			": %s: Device %u: fb_register_client failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);

		return (OMAPLFB_ERROR_GENERIC);
	}

	eError = OMAPLFBUnblankDisplay(psDevInfo);
	if (eError != OMAPLFB_OK)
	{
		printk(KERN_ERR DRIVER_PREFIX
			": %s: Device %u: UnblankDisplay failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eError);
		return eError;
	}

#ifdef CONFIG_HAS_EARLYSUSPEND
	psDevInfo->sEarlySuspend.suspend = OMAPLFBEarlySuspendHandler;
	psDevInfo->sEarlySuspend.resume = OMAPLFBEarlyResumeHandler;
	psDevInfo->sEarlySuspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1;
	register_early_suspend(&psDevInfo->sEarlySuspend);
#endif

	return (OMAPLFB_OK);
}
Beispiel #21
0
static enum PVRSRV_ERROR EnableLFBEventNotification(struct OMAPLFB_DEVINFO
								   *psDevInfo)
{
	int res;
	struct OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;

	memset(&psDevInfo->sLINNotifBlock, 0,
	       sizeof(psDevInfo->sLINNotifBlock));

	psDevInfo->sLINNotifBlock.notifier_call = FrameBufferEvents;

	psSwapChain->bBlanked = IMG_FALSE;

	res = fb_register_client(&psDevInfo->sLINNotifBlock);
	if (res != 0) {
		printk(KERN_WARNING DRIVER_PREFIX
		       ": fb_register_client failed (%d)", res);

		return PVRSRV_ERROR_GENERIC;
	}

	return PVRSRV_OK;
}
static int __init cpufreq_limit_manager_init(void)
{
	int rc;

	rc = sysfs_create_group(kernel_kobj, &cpufreq_limit_manager_attr_group);

	if (rc) {
		pr_info("%s sysfs create failed!\n", __FUNCTION__);
		return -EFAULT;
	}

#if defined(CONFIG_POWERSUSPEND)
	register_power_suspend(&cpufreq_limit_suspend_driver);
#elif defined(CONFIG_HAS_EARLYSUSPEND)
	register_early_suspend(&cpufreq_limit_suspend_driver);
#else
	notif.notifier_call = fb_notifier_callback;
	if (fb_register_client(&notif))
		pr_err("Failed to register FB notifier callback for cpufreq limit manager\n");
#endif  /* CONFIG_POWERSUSPEND || CONFIG_HAS_EARLYSUSPEND || FB NOTIFIER */

	return (rc);
}
Beispiel #23
0
/*!
 * This function is called whenever the SPI slave device is detected.
 *
 * @param	spi	the SPI slave device
 *
 * @return 	Returns 0 on SUCCESS and error on FAILURE.
 */
static int __devinit lcd_probe(struct device *dev)
{
	int ret = 0;
	int i;
	struct mxc_lcd_platform_data *plat = dev->platform_data;

	ch7036_VGA_enable(1);

	for (i = 0; i < num_registered_fb; i++) {
		if (strcmp(registered_fb[i]->fix.id, "DISP3 BG - DI1") == 0) {
			ret = lcd_init();
			if (ret < 0)
				goto err;
			//lcd_init_fb(registered_fb[i]);
			fb_show_logo(registered_fb[i], 0);
			//lcd_poweron(registered_fb[i]);
		}
	}

	fb_register_client(&nb);
	
	// -> [Walker Chen], 2014/01/29 - VGA reboot
	kthread_run(vga_reboot_thread, NULL, "VGA reboot");

	vga_gpio = irq_to_gpio(ch7036_client->irq);
	gpio_set_debounce( vga_gpio , 1000 ); //1000ms	
	irq_set_irq_wake( ch7036_client->irq , 1 );
	ret = request_irq(ch7036_client->irq, vga_reboot_interrupt,
			IRQF_TRIGGER_FALLING,
			 "ch7036 VGA_in", ch7036_client);
	enable_irq_wake(ch7036_client->irq);
	// <- End.
	
	return 0;
err:
	return ret;
}
static void init_info_data(struct sdchg_info_nochip_t *info)
{
	//struct sdchg_info_personal_t *pData = info->pData;

	info->need_state = SDCHG_STATE_NONE;
	info->set_state = SDCHG_STATE_NONE;

	wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
		   "sdchg");
	info->wake_lock_set =false;

	wake_lock_init(&info->end_wake_lock, WAKE_LOCK_SUSPEND,
		   "sdchg_end");

	info->state_machine_run = false;

#ifdef CONFIG_FB
	info->display_on = false;
	info->fb_nb.notifier_call = sdchg_fb_notifier_callback;
	fb_register_client(&info->fb_nb);
#endif

	return;
}
int __init init_gavini_display_devices(void)
{
	int ret;

	ret = fb_register_client(&framebuffer_nb);
	if (ret)
		pr_warning("Failed to register framebuffer notifier\n");
	 
	ret = mcde_dss_register_notifier(&display_nb);
	if (ret)
		pr_warning("Failed to register dss notifier\n");
	 
	if (display_initialized_during_boot) {
		generic_display0.power_mode = MCDE_DISPLAY_PM_ON;
		gavini_dpi_pri_display_info.platform_enabled = 1;
	}

	/*
	 * The pixclock setting is not used within MCDE. The clock is
	 * setup elsewhere. But the pixclock value is visible in user
	 * space.
	 */
	gavini_dpi_pri_display_info.video_mode.pixclock /= port0.phy.dpi.clock_div;

	ret = mcde_display_device_register(&generic_display0);
	if (ret)
		pr_warning("Failed to register generic display device 0\n");

	#ifndef CONFIG_HAS_EARLYSUSPEND
	dpi_pins = ux500_pins_get("mcde-dpi");
	if (!dpi_pins)
		return -EINVAL;
	#endif

	return ret;
}
static int mdnie_register_fb(struct mdnie_info *mdnie)
{
	memset(&mdnie->fb_notif, 0, sizeof(mdnie->fb_notif));
	mdnie->fb_notif.notifier_call = fb_notifier_callback;
	return fb_register_client(&mdnie->fb_notif);
}
Beispiel #27
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;
}
Beispiel #28
0
static int pwm_backlight_probe(struct platform_device *pdev)
{
	struct platform_pwm_backlight_data *data = pdev->dev.platform_data;
	struct backlight_device *bl;
	struct pwm_bl_data *pb;
	int ret;

	if (!data) {
		dev_err(&pdev->dev, "failed to find platform data\n");
		return -EINVAL;
	}

	if (data->init) {
		ret = data->init(&pdev->dev);
		if (ret < 0)
			return ret;
	}

	pb = kzalloc(sizeof(*pb), GFP_KERNEL);
	if (!pb) {
		dev_err(&pdev->dev, "no memory for state\n");
		ret = -ENOMEM;
		goto err_alloc;
	}

	pb->period = data->pwm_period_ns;
	pb->notify = data->notify;
	pb->power = data->power;

	pb->pwm = pwm_request(data->pwm_id, "backlight");
	if (IS_ERR(pb->pwm)) {
		dev_err(&pdev->dev, "unable to request PWM for backlight\n");
		ret = PTR_ERR(pb->pwm);
		goto err_pwm;
	} else
		dev_dbg(&pdev->dev, "got pwm for backlight\n");

	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
			pb, &pwm_backlight_ops);
	if (IS_ERR(bl)) {
		dev_err(&pdev->dev, "failed to register backlight\n");
		ret = PTR_ERR(bl);
		goto err_bl;
	}

	pb->notifier.notifier_call = pwm_bl_notifier_call;

	ret = fb_register_client(&pb->notifier);

	bl->props.max_brightness = data->max_brightness;
	bl->props.brightness = data->dft_brightness;
	backlight_update_status(bl);

	platform_set_drvdata(pdev, bl);
	return 0;

err_bl:
	pwm_free(pb->pwm);
err_pwm:
	kfree(pb);
err_alloc:
	if (data->exit)
		data->exit(&pdev->dev);
	return ret;
}
Beispiel #29
0
/*!
 * This function is called by the driver framework to initialize the LDB
 * device.
 *
 * @param	dev	The device structure for the LDB passed in by the
 *			driver framework.
 *
 * @return      Returns 0 on success or negative error code on error
 */
static int ldb_probe(struct platform_device *pdev)
{
	int ret = 0, i, ipu_di, ipu_di_pix_fmt[2];
	bool primary = false, find_1080p = false;
	struct resource *res;
	struct ldb_platform_data *plat_data = pdev->dev.platform_data;
	mm_segment_t old_fs;
	struct clk *ldb_clk_parent;
	unsigned long ldb_clk_prate = 455000000;
	struct fb_var_screeninfo *var[2];
	uint32_t reg;
	struct device *temp;
	int mxc_ldb_major;
	const struct fb_videomode *mode;
	struct class *mxc_ldb_class;

	if (g_enable_ldb == false)
		return -ENODEV;

	spin_lock_init(&ldb_lock);

	g_ldb_dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (IS_ERR(res))
		return -ENODEV;

	memset(&ldb, 0, sizeof(struct ldb_data));
	enabled[0] = enabled[1] = false;
	var[0] = var[1] = NULL;
	if (g_boot_cmd) {
		ldb.chan_mode_opt = g_chan_mode_opt;
		ldb.chan_bit_map[0] = g_chan_bit_map[0];
		ldb.chan_bit_map[1] = g_chan_bit_map[1];
	}

	ldb.base_addr = res->start;
	ldb_reg = ioremap(ldb.base_addr, res->end - res->start + 1);
	ldb.control_reg = ldb_reg + 2;

	INIT_LIST_HEAD(&ldb.modelist);
	for (i = 0; i < mxcfb_ldb_modedb_sz; i++)
		fb_add_videomode(&mxcfb_ldb_modedb[i], &ldb.modelist);

	for (i = 0; i < num_registered_fb; i++) {
		if ((registered_fb[i]->var.sync & FB_SYNC_EXT) &&
		    (registered_fb[i]->var.vmode == FB_VMODE_NONINTERLACED)) {
			ldb.fbi[i] = registered_fb[i];

			mode = fb_match_mode(&ldb.fbi[i]->var, &ldb.modelist);
			if (mode) {
				dev_dbg(g_ldb_dev, "fb mode found\n");
				fb_videomode_to_var(&ldb.fbi[i]->var, mode);
			} else {
				dev_warn(g_ldb_dev,
						"can't find video mode\n");
				goto err0;
			}
			/*
			 * Default ldb mode:
			 * 1080p: DI0 split, SPWG or DI1 split, SPWG
			 * others: single, SPWG
			 */
			if (g_boot_cmd == false) {
				if (fb_mode_is_equal(mode, &mxcfb_ldb_modedb[0])) {
					if (strcmp(ldb.fbi[i]->fix.id,
					    "DISP3 BG") == 0) {
						ldb.chan_mode_opt = LDB_SPL_DI0;
						dev_warn(g_ldb_dev,
							"default di0 split mode\n");
					} else if (strcmp(ldb.fbi[i]->fix.id,
						   "DISP3 BG - DI1") == 0) {
						ldb.chan_mode_opt = LDB_SPL_DI1;
						dev_warn(g_ldb_dev,
							"default di1 split mode\n");
					}
					ldb.chan_bit_map[0] = LDB_BIT_MAP_SPWG;
					ldb.chan_bit_map[1] = LDB_BIT_MAP_SPWG;
					find_1080p = true;
				} else if (!find_1080p) {
					if (strcmp(ldb.fbi[i]->fix.id,
					    "DISP3 BG") == 0) {
						ldb.chan_mode_opt = LDB_SIN_DI0;
						ldb.chan_bit_map[0] = LDB_BIT_MAP_SPWG;
						dev_warn(g_ldb_dev,
							 "default di0 single mode\n");
					} else if (strcmp(ldb.fbi[i]->fix.id,
						   "DISP3 BG - DI1") == 0) {
						ldb.chan_mode_opt = LDB_SIN_DI1;
						ldb.chan_bit_map[1] = LDB_BIT_MAP_SPWG;
						dev_warn(g_ldb_dev,
							 "default di1 single mode\n");
					}
				}
			}

			acquire_console_sem();
			fb_blank(ldb.fbi[i], FB_BLANK_POWERDOWN);
			release_console_sem();

			if (i == 0)
				primary = true;

			if (ldb.fbi[1] != NULL)
				break;
		}
	}

	/*
	 * We cannot support two LVDS panel with different pixel clock rates
	 * except that one's pixel clock rate is two times of the others'.
	 */
	if (ldb.fbi[1] && ldb.fbi[0] != NULL) {
		if (ldb.fbi[0]->var.pixclock != ldb.fbi[1]->var.pixclock &&
		    ldb.fbi[0]->var.pixclock != 2 * ldb.fbi[1]->var.pixclock &&
		    ldb.fbi[1]->var.pixclock != 2 * ldb.fbi[0]->var.pixclock)
			return -EINVAL;
	}

	ldb.bgref_rmode = plat_data->ext_ref;
	ldb.lvds_bg_reg = regulator_get(&pdev->dev, plat_data->lvds_bg_reg);
	if (!IS_ERR(ldb.lvds_bg_reg)) {
		regulator_set_voltage(ldb.lvds_bg_reg, 2500000, 2500000);
		regulator_enable(ldb.lvds_bg_reg);
	}

	for (i = 0; i < 2; i++) {
		if (ldb.fbi[i] != NULL) {
			if (strcmp(ldb.fbi[i]->fix.id, "DISP3 BG") == 0)
				ipu_di = 0;
			else if (strcmp(ldb.fbi[i]->fix.id, "DISP3 BG - DI1")
				 == 0)
				ipu_di = 1;
			else {
				dev_err(g_ldb_dev, "Wrong framebuffer\n");
				goto err0;
			}

			var[ipu_di] = &ldb.fbi[i]->var;
			if (ldb.fbi[i]->fbops->fb_ioctl) {
				old_fs = get_fs();
				set_fs(KERNEL_DS);
				ldb.fbi[i]->fbops->fb_ioctl(ldb.fbi[i],
						MXCFB_GET_DIFMT,
						(unsigned long)&(ipu_di_pix_fmt[ipu_di]));
				set_fs(old_fs);
			} else {
				dev_err(g_ldb_dev, "Can't get framebuffer "
						   "information\n");
				goto err0;
			}

			if (!valid_mode(ipu_di_pix_fmt[ipu_di])) {
				dev_err(g_ldb_dev, "Unsupport pixel format "
						   "for ldb input\n");
				goto err0;
			}

			reg = __raw_readl(ldb.control_reg);
			if (var[ipu_di]->sync & FB_SYNC_VERT_HIGH_ACT) {
				if (ipu_di == 0)
					__raw_writel((reg &
						~LDB_DI0_VS_POL_MASK) |
						LDB_DI0_VS_POL_ACT_HIGH,
						ldb.control_reg);
				else
					__raw_writel((reg &
						~LDB_DI1_VS_POL_MASK) |
						LDB_DI1_VS_POL_ACT_HIGH,
						ldb.control_reg);
			} else {
				if (ipu_di == 0)
					__raw_writel((reg &
						~LDB_DI0_VS_POL_MASK) |
						LDB_DI0_VS_POL_ACT_LOW,
						ldb.control_reg);
				else
					__raw_writel((reg &
						~LDB_DI1_VS_POL_MASK) |
						LDB_DI1_VS_POL_ACT_LOW,
						ldb.control_reg);
			}

			/* TODO:Set the correct pll4 rate for all situations */
			if (ipu_di == 1) {
				ldb.ldb_di_clk[1] =
					clk_get(&pdev->dev, "ldb_di1_clk");
				ldb_clk_parent =
					clk_get_parent(ldb.ldb_di_clk[1]);
				clk_set_rate(ldb_clk_parent, ldb_clk_prate);
				clk_put(ldb.ldb_di_clk[1]);
			} else {
				ldb.ldb_di_clk[0] =
					clk_get(&pdev->dev, "ldb_di0_clk");
				ldb_clk_parent =
					clk_get_parent(ldb.ldb_di_clk[0]);
				clk_set_rate(ldb_clk_parent, ldb_clk_prate);
				clk_put(ldb.ldb_di_clk[0]);
			}
		}
	}

	reg = __raw_readl(ldb.control_reg);
	if (ldb.bgref_rmode == LDB_EXT_REF)
		__raw_writel((reg & ~LDB_BGREF_RMODE_MASK) |
			      LDB_BGREF_RMODE_EXT, ldb.control_reg);
	else
		__raw_writel((reg & ~LDB_BGREF_RMODE_MASK) |
			      LDB_BGREF_RMODE_INT, ldb.control_reg);

	switch (ldb.chan_mode_opt) {
	case LDB_SIN_DI0:
		if (var[0] == NULL) {
			dev_err(g_ldb_dev, "Can't find framebuffer on DI0\n");
			break;
		}

		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[0]) == 24)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
				      LDB_DATA_WIDTH_CH0_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[0]) == 18)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
				      LDB_DATA_WIDTH_CH0_18,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_JEIDA,
				      ldb.control_reg);

		ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk");
		clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7);
		clk_enable(ldb.ldb_di_clk[0]);
		clk_put(ldb.ldb_di_clk[0]);

		reg = __raw_readl(ldb.control_reg);
		__raw_writel((reg & ~LDB_CH0_MODE_MASK) |
			      LDB_CH0_MODE_EN_TO_DI0, ldb.control_reg);
		ldb.ch_working[0] = true;
		break;
	case LDB_SIN_DI1:
		if (var[1] == NULL) {
			dev_err(g_ldb_dev, "Can't find framebuffer on DI1\n");
			break;
		}

		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[1]) == 24)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
				      LDB_DATA_WIDTH_CH1_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[1]) == 18)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
				      LDB_DATA_WIDTH_CH1_18,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_JEIDA,
				      ldb.control_reg);

		ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk");
		clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7);
		clk_enable(ldb.ldb_di_clk[1]);
		clk_put(ldb.ldb_di_clk[1]);

		reg = __raw_readl(ldb.control_reg);
		__raw_writel((reg & ~LDB_CH1_MODE_MASK) |
			      LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg);
		ldb.ch_working[1] = true;
		break;
	case LDB_SEP:
		if (var[0] == NULL || var[1] == NULL) {
			dev_err(g_ldb_dev, "Can't find framebuffers on DI0/1\n");
			break;
		}

		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[0]) == 24)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
				      LDB_DATA_WIDTH_CH0_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[0]) == 18)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
				      LDB_DATA_WIDTH_CH0_18,
				      ldb.control_reg);
		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[1]) == 24)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
				      LDB_DATA_WIDTH_CH1_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[1]) == 18)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
				      LDB_DATA_WIDTH_CH1_18,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_JEIDA,
				      ldb.control_reg);
		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_JEIDA,
				      ldb.control_reg);

		ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk");
		clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7);
		clk_enable(ldb.ldb_di_clk[0]);
		clk_put(ldb.ldb_di_clk[0]);
		ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk");
		clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7);
		clk_enable(ldb.ldb_di_clk[1]);
		clk_put(ldb.ldb_di_clk[1]);

		reg = __raw_readl(ldb.control_reg);
		__raw_writel((reg & ~(LDB_CH0_MODE_MASK |
				      LDB_CH1_MODE_MASK)) |
			      LDB_CH0_MODE_EN_TO_DI0 |
			      LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg);
		ldb.ch_working[0] = true;
		ldb.ch_working[1] = true;
		break;
	case LDB_DUL_DI0:
	case LDB_SPL_DI0:
		if (var[0] == NULL) {
			dev_err(g_ldb_dev, "Can't find framebuffer on DI0\n");
			break;
		}

		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[0]) == 24)
			__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
					      LDB_DATA_WIDTH_CH1_MASK)) |
				      LDB_DATA_WIDTH_CH0_24 |
				      LDB_DATA_WIDTH_CH1_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[0]) == 18)
			__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
					      LDB_DATA_WIDTH_CH1_MASK)) |
				      LDB_DATA_WIDTH_CH0_18 |
				      LDB_DATA_WIDTH_CH1_18,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_JEIDA,
				      ldb.control_reg);
		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_JEIDA,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_mode_opt == LDB_SPL_DI0)
			__raw_writel(reg | LDB_SPLIT_MODE_EN,
				      ldb.control_reg);

		ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk");
		ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk");
		if (ldb.chan_mode_opt == LDB_DUL_DI0) {
			clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7);
		} else {
			clk_set_rate(ldb.ldb_di_clk[0], 2*ldb_clk_prate/7);
			clk_set_rate(ldb.ldb_di_clk[1], 2*ldb_clk_prate/7);
		}
		clk_enable(ldb.ldb_di_clk[0]);
		clk_enable(ldb.ldb_di_clk[1]);
		clk_put(ldb.ldb_di_clk[0]);
		clk_put(ldb.ldb_di_clk[1]);

		reg = __raw_readl(ldb.control_reg);
		__raw_writel((reg & ~(LDB_CH0_MODE_MASK |
				      LDB_CH1_MODE_MASK)) |
			      LDB_CH0_MODE_EN_TO_DI0 |
			      LDB_CH1_MODE_EN_TO_DI0, ldb.control_reg);
		ldb.ch_working[0] = true;
		ldb.ch_working[1] = true;
		break;
	case LDB_DUL_DI1:
	case LDB_SPL_DI1:
		if (var[1] == NULL) {
			dev_err(g_ldb_dev, "Can't find framebuffer on DI1\n");
			break;
		}

		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[1]) == 24)
			__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
					      LDB_DATA_WIDTH_CH1_MASK)) |
				      LDB_DATA_WIDTH_CH0_24 |
				      LDB_DATA_WIDTH_CH1_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[1]) == 18)
			__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
					      LDB_DATA_WIDTH_CH1_MASK)) |
				      LDB_DATA_WIDTH_CH0_18 |
				      LDB_DATA_WIDTH_CH1_18,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_JEIDA,
				      ldb.control_reg);
		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_JEIDA,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_mode_opt == LDB_SPL_DI1)
			__raw_writel(reg | LDB_SPLIT_MODE_EN,
				      ldb.control_reg);

		ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk");
		ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk");
		if (ldb.chan_mode_opt == LDB_DUL_DI1) {
			clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7);
		} else {
			clk_set_rate(ldb.ldb_di_clk[0], 2*ldb_clk_prate/7);
			clk_set_rate(ldb.ldb_di_clk[1], 2*ldb_clk_prate/7);
		}
		clk_enable(ldb.ldb_di_clk[0]);
		clk_enable(ldb.ldb_di_clk[1]);
		clk_put(ldb.ldb_di_clk[0]);
		clk_put(ldb.ldb_di_clk[1]);

		reg = __raw_readl(ldb.control_reg);
		__raw_writel((reg & ~(LDB_CH0_MODE_MASK |
				      LDB_CH1_MODE_MASK)) |
			      LDB_CH0_MODE_EN_TO_DI1 |
			      LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg);
		ldb.ch_working[0] = true;
		ldb.ch_working[1] = true;
		break;
	default:
		break;
	}

	mxc_ldb_major = register_chrdev(0, "mxc_ldb", &mxc_ldb_fops);
	if (mxc_ldb_major < 0) {
		dev_err(g_ldb_dev, "Unable to register MXC LDB as a char "
				   "device\n");
		ret = mxc_ldb_major;
		goto err0;
	}

	mxc_ldb_class = class_create(THIS_MODULE, "mxc_ldb");
	if (IS_ERR(mxc_ldb_class)) {
		dev_err(g_ldb_dev, "Unable to create class for MXC LDB\n");
		ret = PTR_ERR(mxc_ldb_class);
		goto err1;
	}

	temp = device_create(mxc_ldb_class, NULL, MKDEV(mxc_ldb_major, 0),
			NULL, "mxc_ldb");
	if (IS_ERR(temp)) {
		dev_err(g_ldb_dev, "Unable to create class device for "
				   "MXC LDB\n");
		ret = PTR_ERR(temp);
		goto err2;
	}

	ret = fb_register_client(&nb);
	if (ret < 0)
		goto err2;

	if (primary && ldb.fbi[0] != NULL) {
		acquire_console_sem();
		fb_blank(ldb.fbi[0], FB_BLANK_UNBLANK);
		release_console_sem();
		fb_show_logo(ldb.fbi[0], 0);
	}

	return ret;
err2:
	class_destroy(mxc_ldb_class);
err1:
	unregister_chrdev(mxc_ldb_major, "mxc_ldb");
err0:
	iounmap(ldb_reg);
	return ret;
}
static int  vga_edid_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    char buf[EDID_LENGTH];
    struct fb_monspecs specs;
    struct fb_videomode *moded;
    int ret = -1;
    int gpio, rc,flag;
    unsigned long data;
    struct regulator * ldo;
    struct device_node *vga_node = client->dev.of_node;
    
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 
		return -ENODEV;

    ldo = regulator_get(NULL, "act_ldo3");
		if (ldo == NULL) {
				pr_err("\n%s get ldo3 failed\n", __func__);
		} else{
				regulator_set_voltage(ldo, 1800000, 1800000);
				ret = regulator_enable(ldo);
				if(ret != 0){
						pr_err("%s: faild to enable ldo3\n", __func__);
				} else {
						pr_info("%s: turn on ldo3 done.\n", __func__);
				}
	}
    ldo = regulator_get(NULL, "act_ldo4");
	if (ldo == NULL) {
			pr_err("\n%s get ldo failed\n", __func__);
		} else{
			regulator_set_voltage(ldo, 3300000, 3300000);
			ret = regulator_enable(ldo);
			if(ret != 0){
					pr_err("%s: faild to enable ldo4.\n", __func__);
			} else {
					pr_info("%s: turn on ldo done.\n", __func__);
	        }
	}
	    ldo = regulator_get(NULL, "act_ldo2");
	if (ldo == NULL) {
		pr_err("\n%s get ldo2 failed\n", __func__);
	} else{
			regulator_set_voltage(ldo, 1000000, 1000000);
			ret = regulator_enable(ldo);
			if(ret != 0){
					pr_err("%s: faild to enable ldo2\n", __func__);
			} else {
					pr_info("%s: turn on ldo2 done.\n", __func__);
			}
	}
	ldo = regulator_get(NULL, "act_ldo8");
	if (ldo == NULL) {
			pr_err("\n%s get ldo8 failed\n", __func__);
	} else{
			regulator_set_voltage(ldo, 1800000, 1800000);
			ret = regulator_enable(ldo);
			if(ret != 0){
				pr_err("%s: faild to enable ldo8.\n", __func__);
			} else {
				pr_info("%s: turn on ldo done.\n", __func__);
			}
	}

	ddev = kzalloc(sizeof(struct vga_ddc_dev), GFP_KERNEL);
	if (ddev == NULL) 
		return -ENOMEM;
	
    INIT_LIST_HEAD(&ddev->modelist);
	ddev->client = client;

    gpio = of_get_named_gpio_flags(vga_node,"gpio-pwn", 0,&flag);
	if (!gpio_is_valid(gpio)){
		printk("invalid gpio-pwn: %d\n",gpio);
		return -1;
	} 
    ret = gpio_request(gpio, "vga_pwn");
	if (ret != 0) {
		gpio_free(gpio);
		ret = -EIO;
		goto failed_1;
	}
	ddev->gpio_pwn = gpio;
	ddev->gpio_pwn_enable = (flag == OF_GPIO_ACTIVE_LOW)? 0:1;
#ifdef CONFIG_FIREFLY_VGA_OUT_ONLY
	gpio_direction_output(ddev->gpio_pwn, !(ddev->gpio_pwn_enable));
#else	
    gpio_direction_output(ddev->gpio_pwn, ddev->gpio_pwn_enable);
    
	gpio = of_get_named_gpio_flags(vga_node,"gpio-sel", 0,&flag);
	if (!gpio_is_valid(gpio)){
		printk("invalid gpio-sel: %d\n",gpio);
		return -1;
	} 
   ret = gpio_request(gpio, "vga_sel");
	if (ret != 0) {
		gpio_free(gpio);
		ret = -EIO;
		goto failed_1;
	}
	ddev->gpio_sel = gpio;
	ddev->gpio_sel_enable = (flag == OF_GPIO_ACTIVE_LOW)? 0:1;
	gpio_direction_output(ddev->gpio_sel, ddev->gpio_sel_enable);
#endif

	of_property_read_u32(vga_node, "rockchip,source", &(rc));
	ddev->video_source = rc;
	of_property_read_u32(vga_node, "rockchip,prop", &(rc));
	ddev->property = rc - 1;
	
    ddev->modeNum = vga_switch_default_screen();
    
#ifndef CONFIG_FIREFLY_VGA_OUT_ONLY    
    vga_switch_source(VGA_SOURCE_EXTERN); 
#endif    

    printk("%s: success. %d \n", __func__,ddev->modeNum);
    

    
    //setup_timer(&timer_vga_ddc, vga_ddc_timer, data);
    //INIT_DELAYED_WORK(&ddev->work, vga_ddc_timer);
    //schedule_work(&chip->work);
    memset(&vga_monspecs, 0, sizeof(struct sda7123_monspecs));
    
    ddev->vga = &vga_monspecs;
	#ifdef CONFIG_SWITCH
	ddev->switchdev.name="vga";
	ddev->switchdev.print_name = vga_print_name;
	switch_dev_register(&(ddev->switchdev));
	#endif
    
    mutex_init(&ddev->vga->lock);
    
	ddev->vga->workqueue = create_singlethread_workqueue("vga");
	if (ddev->vga->workqueue == NULL) {
		printk(KERN_ERR "vga,: create workqueue failed.\n");
		goto failed_1;
	}

    ddev->first_start = 1;
    ddev->set_mode = 0;

	firefly_register_display_vga(&client->dev);
	
	fb_register_client(&firefly_fb_notifier);
	
	
	vga_submit_work(ddev->vga, VGA_TIMER_DELAY, 8000, NULL);
	
	return 0;
failed_1:
	return ret;
}