msm_fb: display: Send vsync events using sysfs for MDP3 targets

Replace sending of vsync timestamp using uevents with sysfs entry
as uevent result in increase in power numbers due to broadcast in
nature.

Change-Id: I22cfbd68c8bcbe4a47e94074393f1cbf79920c58
Signed-off-by: Mayank Chopra <makchopra@codeaurora.org>
Signed-off-by: Siddhartha Agrawal <agrawals@codeaurora.org>

Conflicts:

	drivers/video/msm/mdp_dma.c

Signed-off-by: Siddhartha Agrawal <agrawals@codeaurora.org>
This commit is contained in:
Mayank Chopra 2012-09-18 20:34:16 +05:30 committed by Stephen Boyd
parent eb35bd3bc5
commit 69d205069c
5 changed files with 168 additions and 17 deletions

View file

@ -1309,27 +1309,32 @@ error:
}
#endif
static void send_vsync_work(struct work_struct *work)
{
char buf[64];
char *envp[2];
snprintf(buf, sizeof(buf), "VSYNC=%llu",
ktime_to_ns(vsync_cntrl.vsync_time));
envp[0] = buf;
envp[1] = NULL;
kobject_uevent_env(&(vsync_cntrl.dev->kobj), KOBJ_CHANGE, envp);
}
#ifdef CONFIG_FB_MSM_MDP303
/* vsync_isr_handler: Called from isr context*/
static void vsync_isr_handler(void)
{
vsync_cntrl.vsync_time = ktime_get();
schedule_work(&(vsync_cntrl.vsync_work));
}
#endif
static ssize_t vsync_show_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret = 0;
if (atomic_read(&vsync_cntrl.suspend) > 0 ||
atomic_read(&vsync_cntrl.vsync_resume) == 0)
return 0;
INIT_COMPLETION(vsync_cntrl.vsync_wait);
wait_for_completion(&vsync_cntrl.vsync_wait);
ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu",
ktime_to_ns(vsync_cntrl.vsync_time));
buf[strlen(buf) + 1] = '\0';
return ret;
}
/* Returns < 0 on error, 0 on timeout, or > 0 on successful wait */
int mdp_ppp_pipe_wait(void)
{
@ -1814,6 +1819,8 @@ irqreturn_t mdp_isr(int irq, void *ptr)
if (!vsync_isr)
mdp_pipe_ctrl(MDP_CMD_BLOCK,
MDP_BLOCK_POWER_OFF, TRUE);
complete_all(&vsync_cntrl.vsync_wait);
}
/* DMA3 TV-Out Start */
@ -1882,6 +1889,8 @@ irqreturn_t mdp_isr(int irq, void *ptr)
if (!vsync_isr)
mdp_pipe_ctrl(MDP_CMD_BLOCK,
MDP_BLOCK_POWER_OFF, TRUE);
complete_all(&vsync_cntrl.vsync_wait);
}
/* DMA2 LCD-Out Complete */
@ -2011,8 +2020,9 @@ static void mdp_drv_init(void)
for (i = 0; i < MDP_MAX_BLOCK; i++) {
atomic_set(&mdp_block_power_cnt[i], 0);
}
INIT_WORK(&(vsync_cntrl.vsync_work), send_vsync_work);
vsync_cntrl.disabled_clocks = 1;
init_completion(&vsync_cntrl.vsync_wait);
atomic_set(&vsync_cntrl.vsync_resume, 1);
#ifdef MSM_FB_ENABLE_DBGFS
{
struct dentry *root;
@ -2098,7 +2108,9 @@ static int mdp_off(struct platform_device *pdev)
pr_debug("%s:+\n", __func__);
mdp_histogram_ctrl_all(FALSE);
atomic_set(&vsync_cntrl.suspend, 1);
atomic_set(&vsync_cntrl.vsync_resume, 0);
complete_all(&vsync_cntrl.vsync_wait);
mdp_clk_ctrl(1);
if (mfd->panel.type == MIPI_CMD_PANEL)
mdp4_dsi_cmd_off(pdev);
@ -2129,7 +2141,16 @@ void mdp4_hw_init(void)
{
/* empty */
}
#endif
static DEVICE_ATTR(vsync_event, S_IRUGO, vsync_show_event, NULL);
static struct attribute *vsync_fs_attrs[] = {
&dev_attr_vsync_event.attr,
NULL,
};
static struct attribute_group vsync_fs_attr_group = {
.attrs = vsync_fs_attrs,
};
static int mdp_on(struct platform_device *pdev)
{
@ -2159,10 +2180,26 @@ static int mdp_on(struct platform_device *pdev)
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
if ((mdp_rev == MDP_REV_303) &&
(mfd->panel.type == MIPI_CMD_PANEL))
if (mdp_rev == MDP_REV_303 && mfd->panel.type == MIPI_CMD_PANEL) {
vsync_cntrl.dev = mfd->fbi->dev;
if (!vsync_cntrl.sysfs_created) {
ret = sysfs_create_group(&vsync_cntrl.dev->kobj,
&vsync_fs_attr_group);
if (ret) {
pr_err("%s: sysfs creation failed, ret=%d\n",
__func__, ret);
return ret;
}
kobject_uevent(&vsync_cntrl.dev->kobj, KOBJ_ADD);
pr_debug("%s: kobject_uevent(KOBJ_ADD)\n", __func__);
vsync_cntrl.sysfs_created = 1;
}
atomic_set(&vsync_cntrl.suspend, 0);
}
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
ret = panel_next_on(pdev);

View file

@ -97,6 +97,10 @@ struct vsync {
struct work_struct vsync_work;
int vsync_irq_enabled;
int disabled_clocks;
struct completion vsync_wait;
atomic_t suspend;
atomic_t vsync_resume;
int sysfs_created;
};
extern struct vsync vsync_cntrl;

View file

@ -520,6 +520,9 @@ void mdp_dma_vsync_ctrl(int enable)
return;
spin_lock_irqsave(&mdp_spin_lock, flag);
if (!enable)
INIT_COMPLETION(vsync_cntrl.vsync_wait);
vsync_cntrl.vsync_irq_enabled = enable;
if (!enable)
vsync_cntrl.disabled_clocks = 0;
@ -536,6 +539,9 @@ void mdp_dma_vsync_ctrl(int enable)
mdp_enable_irq(MDP_VSYNC_TERM);
spin_unlock_irqrestore(&mdp_spin_lock, flag);
}
if (vsync_cntrl.vsync_irq_enabled &&
atomic_read(&vsync_cntrl.suspend) == 0)
atomic_set(&vsync_cntrl.vsync_resume, 1);
}
void mdp_lcd_update_workqueue_handler(struct work_struct *work)

View file

@ -34,6 +34,33 @@
static int first_pixel_start_x;
static int first_pixel_start_y;
static ssize_t vsync_show_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret = 0;
INIT_COMPLETION(vsync_cntrl.vsync_wait);
if (atomic_read(&vsync_cntrl.suspend) > 0 ||
atomic_read(&vsync_cntrl.vsync_resume) == 0)
return 0;
wait_for_completion(&vsync_cntrl.vsync_wait);
ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu",
ktime_to_ns(vsync_cntrl.vsync_time));
buf[strlen(buf) + 1] = '\0';
return ret;
}
static DEVICE_ATTR(vsync_event, S_IRUGO, vsync_show_event, NULL);
static struct attribute *vsync_fs_attrs[] = {
&dev_attr_vsync_event.attr,
NULL,
};
static struct attribute_group vsync_fs_attr_group = {
.attrs = vsync_fs_attrs,
};
int mdp_dsi_video_on(struct platform_device *pdev)
{
int dsi_width;
@ -88,6 +115,7 @@ int mdp_dsi_video_on(struct platform_device *pdev)
var = &fbi->var;
vsync_cntrl.dev = mfd->fbi->dev;
atomic_set(&vsync_cntrl.suspend, 0);
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
@ -226,6 +254,20 @@ int mdp_dsi_video_on(struct platform_device *pdev)
/* MDP cmd block disable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
if (!vsync_cntrl.sysfs_created) {
ret = sysfs_create_group(&vsync_cntrl.dev->kobj,
&vsync_fs_attr_group);
if (ret) {
pr_err("%s: sysfs creation failed, ret=%d\n",
__func__, ret);
return ret;
}
kobject_uevent(&vsync_cntrl.dev->kobj, KOBJ_ADD);
pr_debug("%s: kobject_uevent(KOBJ_ADD)\n", __func__);
vsync_cntrl.sysfs_created = 1;
}
return ret;
}
@ -241,6 +283,10 @@ int mdp_dsi_video_off(struct platform_device *pdev)
mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
ret = panel_next_off(pdev);
atomic_set(&vsync_cntrl.suspend, 1);
atomic_set(&vsync_cntrl.vsync_resume, 0);
complete_all(&vsync_cntrl.vsync_wait);
/* delay to make sure the last frame finishes */
msleep(20);
@ -255,6 +301,9 @@ void mdp_dma_video_vsync_ctrl(int enable)
return;
spin_lock_irqsave(&mdp_spin_lock, flag);
if (!enable)
INIT_COMPLETION(vsync_cntrl.vsync_wait);
vsync_cntrl.vsync_irq_enabled = enable;
if (!enable)
vsync_cntrl.disabled_clocks = 0;
@ -270,6 +319,9 @@ void mdp_dma_video_vsync_ctrl(int enable)
mdp_enable_irq(MDP_VSYNC_TERM);
spin_unlock_irqrestore(&mdp_spin_lock, flag);
}
if (vsync_cntrl.vsync_irq_enabled &&
atomic_read(&vsync_cntrl.suspend) == 0)
atomic_set(&vsync_cntrl.vsync_resume, 1);
}
void mdp_dsi_video_update(struct msm_fb_data_type *mfd)

View file

@ -51,6 +51,33 @@ extern uint32 mdp_intr_mask;
int first_pixel_start_x;
int first_pixel_start_y;
static ssize_t vsync_show_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret = 0;
if (atomic_read(&vsync_cntrl.suspend) > 0 ||
atomic_read(&vsync_cntrl.vsync_resume) == 0)
return 0;
INIT_COMPLETION(vsync_cntrl.vsync_wait);
wait_for_completion(&vsync_cntrl.vsync_wait);
ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu",
ktime_to_ns(vsync_cntrl.vsync_time));
buf[strlen(buf) + 1] = '\0';
return ret;
}
static DEVICE_ATTR(vsync_event, S_IRUGO, vsync_show_event, NULL);
static struct attribute *vsync_fs_attrs[] = {
&dev_attr_vsync_event.attr,
NULL,
};
static struct attribute_group vsync_fs_attr_group = {
.attrs = vsync_fs_attrs,
};
int mdp_lcdc_on(struct platform_device *pdev)
{
int lcdc_width;
@ -106,6 +133,7 @@ int mdp_lcdc_on(struct platform_device *pdev)
fbi = mfd->fbi;
var = &fbi->var;
vsync_cntrl.dev = mfd->fbi->dev;
atomic_set(&vsync_cntrl.suspend, 0);
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
@ -292,6 +320,20 @@ int mdp_lcdc_on(struct platform_device *pdev)
/* MDP cmd block disable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
if (!vsync_cntrl.sysfs_created) {
ret = sysfs_create_group(&vsync_cntrl.dev->kobj,
&vsync_fs_attr_group);
if (ret) {
pr_err("%s: sysfs creation failed, ret=%d\n",
__func__, ret);
return ret;
}
kobject_uevent(&vsync_cntrl.dev->kobj, KOBJ_ADD);
pr_debug("%s: kobject_uevent(KOBJ_ADD)\n", __func__);
vsync_cntrl.sysfs_created = 1;
}
return ret;
}
@ -321,6 +363,9 @@ int mdp_lcdc_off(struct platform_device *pdev)
ret = panel_next_off(pdev);
up(&mfd->dma->mutex);
atomic_set(&vsync_cntrl.suspend, 1);
atomic_set(&vsync_cntrl.vsync_resume, 0);
complete_all(&vsync_cntrl.vsync_wait);
/* delay to make sure the last frame finishes */
msleep(16);
@ -336,6 +381,9 @@ void mdp_dma_lcdc_vsync_ctrl(int enable)
return;
spin_lock_irqsave(&mdp_spin_lock, flag);
if (!enable)
INIT_COMPLETION(vsync_cntrl.vsync_wait);
vsync_cntrl.vsync_irq_enabled = enable;
if (!enable)
vsync_cntrl.disabled_clocks = 0;
@ -351,6 +399,10 @@ void mdp_dma_lcdc_vsync_ctrl(int enable)
mdp_enable_irq(MDP_VSYNC_TERM);
spin_unlock_irqrestore(&mdp_spin_lock, flag);
}
if (vsync_cntrl.vsync_irq_enabled &&
atomic_read(&vsync_cntrl.suspend) == 0)
atomic_set(&vsync_cntrl.vsync_resume, 1);
}
void mdp_lcdc_update(struct msm_fb_data_type *mfd)