mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
a5abf4721b
The VENC driver currently relies on the timings in omap_dss_device struct to configure the DISPC and VENC blocks accordingly. This makes the VENC interface driver dependent on the omap_dss_device struct. Make the VENC driver data maintain it's own timings field. The panel driver is expected to call omapdss_venc_set_timings() to set these timings before the panel is enabled. Call omapdss_venc_set_timings() before enabling venc output, this is done to atleast have the venc output configured to the panel's default timings if the DSS user didn't explicitly call the venc panel driver's set_timings op. Make the VENC panel driver configure the new timings is the omap_dss_device struct(dssdev->panel.timings). The VENC driver is responsible for maintaining only it's own copy of timings. Signed-off-by: Archit Taneja <archit@ti.com>
248 lines
5.5 KiB
C
248 lines
5.5 KiB
C
/*
|
|
* 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;
|
|
}
|
|
|
|
omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
|
|
|
|
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);
|
|
dssdev->panel.timings = *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);
|
|
}
|