Commit 156fd99e authored by Archit Taneja's avatar Archit Taneja

OMAPDSS: VENC: Split VENC into interface and panel driver

The current venc.c driver contains both the interface and panel driver code.
This makes the driver hard to read, and difficult to understand the work split
between the interface and panel driver and the how the locking works.

This also makes it easier to clearly define the VENC interface ops called by the
panel driver.

Split venc.c into venc.c and venc_panel.c representing the interface and panel
driver respectively. This split is done along the lines of the HDMI interface
and panel drivers.
Signed-off-by: default avatarArchit Taneja <archit@ti.com>
parent 9b4a5716
...@@ -3,7 +3,7 @@ omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ ...@@ -3,7 +3,7 @@ omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
manager.o overlay.o apply.o manager.o overlay.o apply.o
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
......
...@@ -469,6 +469,16 @@ static inline unsigned long venc_get_pixel_clock(void) ...@@ -469,6 +469,16 @@ static inline unsigned long venc_get_pixel_clock(void)
return 0; return 0;
} }
#endif #endif
int omapdss_venc_display_enable(struct omap_dss_device *dssdev);
void omapdss_venc_display_disable(struct omap_dss_device *dssdev);
void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev);
int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss);
int venc_panel_init(void);
void venc_panel_exit(void);
/* HDMI */ /* HDMI */
#ifdef CONFIG_OMAP4_DSS_HDMI #ifdef CONFIG_OMAP4_DSS_HDMI
......
...@@ -427,6 +427,10 @@ static int venc_power_on(struct omap_dss_device *dssdev) ...@@ -427,6 +427,10 @@ static int venc_power_on(struct omap_dss_device *dssdev)
u32 l; u32 l;
int r; int r;
r = venc_runtime_get();
if (r)
goto err0;
venc_reset(); venc_reset();
venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
...@@ -449,26 +453,22 @@ static int venc_power_on(struct omap_dss_device *dssdev) ...@@ -449,26 +453,22 @@ static int venc_power_on(struct omap_dss_device *dssdev)
r = regulator_enable(venc.vdda_dac_reg); r = regulator_enable(venc.vdda_dac_reg);
if (r) if (r)
goto err; goto err1;
if (dssdev->platform_enable)
dssdev->platform_enable(dssdev);
r = dss_mgr_enable(dssdev->manager); r = dss_mgr_enable(dssdev->manager);
if (r) if (r)
goto err; goto err2;
return 0; return 0;
err: err2:
regulator_disable(venc.vdda_dac_reg);
err1:
venc_write_reg(VENC_OUTPUT_CONTROL, 0); venc_write_reg(VENC_OUTPUT_CONTROL, 0);
dss_set_dac_pwrdn_bgz(0); dss_set_dac_pwrdn_bgz(0);
if (dssdev->platform_disable) venc_runtime_put();
dssdev->platform_disable(dssdev); err0:
regulator_disable(venc.vdda_dac_reg);
return r; return r;
} }
...@@ -479,10 +479,9 @@ static void venc_power_off(struct omap_dss_device *dssdev) ...@@ -479,10 +479,9 @@ static void venc_power_off(struct omap_dss_device *dssdev)
dss_mgr_disable(dssdev->manager); dss_mgr_disable(dssdev->manager);
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
regulator_disable(venc.vdda_dac_reg); regulator_disable(venc.vdda_dac_reg);
venc_runtime_put();
} }
unsigned long venc_get_pixel_clock(void) unsigned long venc_get_pixel_clock(void)
...@@ -491,171 +490,95 @@ unsigned long venc_get_pixel_clock(void) ...@@ -491,171 +490,95 @@ unsigned long venc_get_pixel_clock(void)
return 13500000; return 13500000;
} }
static ssize_t display_output_type_show(struct device *dev, int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
struct device_attribute *attr, char *buf)
{ {
struct omap_dss_device *dssdev = to_dss_device(dev); int r;
const char *ret;
switch (dssdev->phy.venc.type) {
case OMAP_DSS_VENC_TYPE_COMPOSITE:
ret = "composite";
break;
case OMAP_DSS_VENC_TYPE_SVIDEO:
ret = "svideo";
break;
default:
return -EINVAL;
}
return snprintf(buf, PAGE_SIZE, "%s\n", ret); DSSDBG("venc_display_enable\n");
}
static ssize_t display_output_type_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
enum omap_dss_venc_type new_type;
if (sysfs_streq("composite", buf))
new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
else if (sysfs_streq("svideo", buf))
new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
else
return -EINVAL;
mutex_lock(&venc.venc_lock); mutex_lock(&venc.venc_lock);
if (dssdev->phy.venc.type != new_type) { if (dssdev->manager == NULL) {
dssdev->phy.venc.type = new_type; DSSERR("Failed to enable display: no manager\n");
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { r = -ENODEV;
venc_power_off(dssdev); goto err0;
venc_power_on(dssdev);
}
} }
mutex_unlock(&venc.venc_lock);
return size;
}
static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
display_output_type_show, display_output_type_store);
/* driver */
static int venc_panel_probe(struct omap_dss_device *dssdev)
{
dssdev->panel.timings = omap_dss_pal_timings;
return device_create_file(&dssdev->dev, &dev_attr_output_type);
}
static void venc_panel_remove(struct omap_dss_device *dssdev)
{
device_remove_file(&dssdev->dev, &dev_attr_output_type);
}
static int venc_panel_enable(struct omap_dss_device *dssdev)
{
int r = 0;
DSSDBG("venc_enable_display\n");
mutex_lock(&venc.venc_lock);
r = omap_dss_start_device(dssdev); r = omap_dss_start_device(dssdev);
if (r) { if (r) {
DSSERR("failed to start device\n"); DSSERR("failed to start device\n");
goto err0; goto err0;
} }
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { if (dssdev->platform_enable)
r = -EINVAL; dssdev->platform_enable(dssdev);
goto err1;
}
r = venc_runtime_get();
if (r)
goto err1;
r = venc_power_on(dssdev); r = venc_power_on(dssdev);
if (r) if (r)
goto err2; goto err1;
venc.wss_data = 0; venc.wss_data = 0;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&venc.venc_lock); mutex_unlock(&venc.venc_lock);
return 0; return 0;
err2:
venc_runtime_put();
err1: err1:
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
omap_dss_stop_device(dssdev); omap_dss_stop_device(dssdev);
err0: err0:
mutex_unlock(&venc.venc_lock); mutex_unlock(&venc.venc_lock);
return r; return r;
} }
static void venc_panel_disable(struct omap_dss_device *dssdev) void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
{ {
DSSDBG("venc_disable_display\n"); DSSDBG("venc_display_disable\n");
mutex_lock(&venc.venc_lock); mutex_lock(&venc.venc_lock);
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
goto end;
if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
/* suspended is the same as disabled with venc */
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
goto end;
}
venc_power_off(dssdev); venc_power_off(dssdev);
venc_runtime_put();
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
omap_dss_stop_device(dssdev); omap_dss_stop_device(dssdev);
end:
mutex_unlock(&venc.venc_lock);
}
static int venc_panel_suspend(struct omap_dss_device *dssdev) if (dssdev->platform_disable)
{ dssdev->platform_disable(dssdev);
venc_panel_disable(dssdev);
return 0;
}
static int venc_panel_resume(struct omap_dss_device *dssdev) mutex_unlock(&venc.venc_lock);
{
return venc_panel_enable(dssdev);
} }
static void venc_set_timings(struct omap_dss_device *dssdev, void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings) struct omap_video_timings *timings)
{ {
DSSDBG("venc_set_timings\n"); DSSDBG("venc_set_timings\n");
mutex_lock(&venc.venc_lock);
/* Reset WSS data when the TV standard changes. */ /* Reset WSS data when the TV standard changes. */
if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings))) if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
venc.wss_data = 0; venc.wss_data = 0;
dssdev->panel.timings = *timings; dssdev->panel.timings = *timings;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
int r;
/* turn the venc off and on to get new timings to use */ /* turn the venc off and on to get new timings to use */
venc_panel_disable(dssdev); venc_power_off(dssdev);
venc_panel_enable(dssdev);
r = venc_power_on(dssdev);
if (r)
DSSERR("failed to power on VENC\n");
} else { } else {
dss_mgr_set_timings(dssdev->manager, timings); dss_mgr_set_timings(dssdev->manager, timings);
} }
mutex_unlock(&venc.venc_lock);
} }
static int venc_check_timings(struct omap_dss_device *dssdev, int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings) struct omap_video_timings *timings)
{ {
DSSDBG("venc_check_timings\n"); DSSDBG("venc_check_timings\n");
...@@ -668,13 +591,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev, ...@@ -668,13 +591,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
return -EINVAL; return -EINVAL;
} }
static u32 venc_get_wss(struct omap_dss_device *dssdev) u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev)
{ {
/* Invert due to VENC_L21_WC_CTL:INV=1 */ /* Invert due to VENC_L21_WC_CTL:INV=1 */
return (venc.wss_data >> 8) ^ 0xfffff; return (venc.wss_data >> 8) ^ 0xfffff;
} }
static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
{ {
const struct venc_config *config; const struct venc_config *config;
int r; int r;
...@@ -703,31 +626,6 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) ...@@ -703,31 +626,6 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
return r; return r;
} }
static struct omap_dss_driver venc_driver = {
.probe = venc_panel_probe,
.remove = venc_panel_remove,
.enable = venc_panel_enable,
.disable = venc_panel_disable,
.suspend = venc_panel_suspend,
.resume = venc_panel_resume,
.get_resolution = omapdss_default_get_resolution,
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
.set_timings = venc_set_timings,
.check_timings = venc_check_timings,
.get_wss = venc_get_wss,
.set_wss = venc_set_wss,
.driver = {
.name = "venc",
.owner = THIS_MODULE,
},
};
/* driver end */
static int __init venc_init_display(struct omap_dss_device *dssdev) static int __init venc_init_display(struct omap_dss_device *dssdev)
{ {
DSSDBG("init_display\n"); DSSDBG("init_display\n");
...@@ -897,9 +795,9 @@ static int __init omap_venchw_probe(struct platform_device *pdev) ...@@ -897,9 +795,9 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
venc_runtime_put(); venc_runtime_put();
r = omap_dss_register_driver(&venc_driver); r = venc_panel_init();
if (r) if (r)
goto err_reg_panel_driver; goto err_panel_init;
dss_debugfs_create_file("venc", venc_dump_regs); dss_debugfs_create_file("venc", venc_dump_regs);
...@@ -907,7 +805,7 @@ static int __init omap_venchw_probe(struct platform_device *pdev) ...@@ -907,7 +805,7 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
return 0; return 0;
err_reg_panel_driver: err_panel_init:
err_runtime_get: err_runtime_get:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
venc_put_clocks(); venc_put_clocks();
...@@ -923,7 +821,7 @@ static int __exit omap_venchw_remove(struct platform_device *pdev) ...@@ -923,7 +821,7 @@ static int __exit omap_venchw_remove(struct platform_device *pdev)
venc.vdda_dac_reg = NULL; venc.vdda_dac_reg = NULL;
} }
omap_dss_unregister_driver(&venc_driver); venc_panel_exit();
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
venc_put_clocks(); venc_put_clocks();
......
/*
* Copyright (C) 2009 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* VENC panel driver
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <video/omapdss.h>
#include "dss.h"
static struct {
struct mutex lock;
} venc_panel;
static ssize_t display_output_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
const char *ret;
switch (dssdev->phy.venc.type) {
case OMAP_DSS_VENC_TYPE_COMPOSITE:
ret = "composite";
break;
case OMAP_DSS_VENC_TYPE_SVIDEO:
ret = "svideo";
break;
default:
return -EINVAL;
}
return snprintf(buf, PAGE_SIZE, "%s\n", ret);
}
static ssize_t display_output_type_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
enum omap_dss_venc_type new_type;
if (sysfs_streq("composite", buf))
new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
else if (sysfs_streq("svideo", buf))
new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
else
return -EINVAL;
mutex_lock(&venc_panel.lock);
if (dssdev->phy.venc.type != new_type) {
dssdev->phy.venc.type = new_type;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
omapdss_venc_display_disable(dssdev);
omapdss_venc_display_enable(dssdev);
}
}
mutex_unlock(&venc_panel.lock);
return size;
}
static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
display_output_type_show, display_output_type_store);
static int venc_panel_probe(struct omap_dss_device *dssdev)
{
/* set default timings to PAL */
const struct omap_video_timings default_timings = {
.x_res = 720,
.y_res = 574,
.pixel_clock = 13500,
.hsw = 64,
.hfp = 12,
.hbp = 68,
.vsw = 5,
.vfp = 5,
.vbp = 41,
.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
.interlace = true,
};
mutex_init(&venc_panel.lock);
dssdev->panel.timings = default_timings;
return device_create_file(&dssdev->dev, &dev_attr_output_type);
}
static void venc_panel_remove(struct omap_dss_device *dssdev)
{
device_remove_file(&dssdev->dev, &dev_attr_output_type);
}
static int venc_panel_enable(struct omap_dss_device *dssdev)
{
int r;
dev_dbg(&dssdev->dev, "venc_panel_enable\n");
mutex_lock(&venc_panel.lock);
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
r = -EINVAL;
goto err;
}
r = omapdss_venc_display_enable(dssdev);
if (r)
goto err;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&venc_panel.lock);
return 0;
err:
mutex_unlock(&venc_panel.lock);
return r;
}
static void venc_panel_disable(struct omap_dss_device *dssdev)
{
dev_dbg(&dssdev->dev, "venc_panel_disable\n");
mutex_lock(&venc_panel.lock);
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
goto end;
if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
/* suspended is the same as disabled with venc */
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
goto end;
}
omapdss_venc_display_disable(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
end:
mutex_unlock(&venc_panel.lock);
}
static int venc_panel_suspend(struct omap_dss_device *dssdev)
{
venc_panel_disable(dssdev);
return 0;
}
static int venc_panel_resume(struct omap_dss_device *dssdev)
{
return venc_panel_enable(dssdev);
}
static void venc_panel_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
dev_dbg(&dssdev->dev, "venc_panel_set_timings\n");
mutex_lock(&venc_panel.lock);
omapdss_venc_set_timings(dssdev, timings);
mutex_unlock(&venc_panel.lock);
}
static int venc_panel_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
dev_dbg(&dssdev->dev, "venc_panel_check_timings\n");
return omapdss_venc_check_timings(dssdev, timings);
}
static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
{
dev_dbg(&dssdev->dev, "venc_panel_get_wss\n");
return omapdss_venc_get_wss(dssdev);
}
static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
{
dev_dbg(&dssdev->dev, "venc_panel_set_wss\n");
return omapdss_venc_set_wss(dssdev, wss);
}
static struct omap_dss_driver venc_driver = {
.probe = venc_panel_probe,
.remove = venc_panel_remove,
.enable = venc_panel_enable,
.disable = venc_panel_disable,
.suspend = venc_panel_suspend,
.resume = venc_panel_resume,
.get_resolution = omapdss_default_get_resolution,
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
.set_timings = venc_panel_set_timings,
.check_timings = venc_panel_check_timings,
.get_wss = venc_panel_get_wss,
.set_wss = venc_panel_set_wss,
.driver = {
.name = "venc",
.owner = THIS_MODULE,
},
};
int venc_panel_init(void)
{
return omap_dss_register_driver(&venc_driver);
}
void venc_panel_exit(void)
{
omap_dss_unregister_driver(&venc_driver);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment