linux/drivers/video/omap2/dss/venc_panel.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2009 Nokia Corporation
   3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
   4 *
   5 * VENC panel driver
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License version 2 as published by
   9 * the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but WITHOUT
  12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14 * more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along with
  17 * this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include <linux/kernel.h>
  21#include <linux/err.h>
  22#include <linux/io.h>
  23#include <linux/mutex.h>
  24#include <linux/module.h>
  25
  26#include <video/omapdss.h>
  27
  28#include "dss.h"
  29
  30static struct {
  31        struct mutex lock;
  32} venc_panel;
  33
  34static ssize_t display_output_type_show(struct device *dev,
  35                struct device_attribute *attr, char *buf)
  36{
  37        struct omap_dss_device *dssdev = to_dss_device(dev);
  38        const char *ret;
  39
  40        switch (dssdev->phy.venc.type) {
  41        case OMAP_DSS_VENC_TYPE_COMPOSITE:
  42                ret = "composite";
  43                break;
  44        case OMAP_DSS_VENC_TYPE_SVIDEO:
  45                ret = "svideo";
  46                break;
  47        default:
  48                return -EINVAL;
  49        }
  50
  51        return snprintf(buf, PAGE_SIZE, "%s\n", ret);
  52}
  53
  54static ssize_t display_output_type_store(struct device *dev,
  55                struct device_attribute *attr, const char *buf, size_t size)
  56{
  57        struct omap_dss_device *dssdev = to_dss_device(dev);
  58        enum omap_dss_venc_type new_type;
  59
  60        if (sysfs_streq("composite", buf))
  61                new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
  62        else if (sysfs_streq("svideo", buf))
  63                new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
  64        else
  65                return -EINVAL;
  66
  67        mutex_lock(&venc_panel.lock);
  68
  69        if (dssdev->phy.venc.type != new_type) {
  70                dssdev->phy.venc.type = new_type;
  71                omapdss_venc_set_type(dssdev, new_type);
  72                if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
  73                        omapdss_venc_display_disable(dssdev);
  74                        omapdss_venc_display_enable(dssdev);
  75                }
  76        }
  77
  78        mutex_unlock(&venc_panel.lock);
  79
  80        return size;
  81}
  82
  83static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
  84                display_output_type_show, display_output_type_store);
  85
  86static int venc_panel_probe(struct omap_dss_device *dssdev)
  87{
  88        /* set default timings to PAL */
  89        const struct omap_video_timings default_timings = {
  90                .x_res          = 720,
  91                .y_res          = 574,
  92                .pixel_clock    = 13500,
  93                .hsw            = 64,
  94                .hfp            = 12,
  95                .hbp            = 68,
  96                .vsw            = 5,
  97                .vfp            = 5,
  98                .vbp            = 41,
  99
 100                .vsync_level    = OMAPDSS_SIG_ACTIVE_HIGH,
 101                .hsync_level    = OMAPDSS_SIG_ACTIVE_HIGH,
 102
 103                .interlace      = true,
 104        };
 105
 106        mutex_init(&venc_panel.lock);
 107
 108        dssdev->panel.timings = default_timings;
 109
 110        return device_create_file(&dssdev->dev, &dev_attr_output_type);
 111}
 112
 113static void venc_panel_remove(struct omap_dss_device *dssdev)
 114{
 115        device_remove_file(&dssdev->dev, &dev_attr_output_type);
 116}
 117
 118static int venc_panel_enable(struct omap_dss_device *dssdev)
 119{
 120        int r;
 121
 122        dev_dbg(&dssdev->dev, "venc_panel_enable\n");
 123
 124        mutex_lock(&venc_panel.lock);
 125
 126        if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
 127                r = -EINVAL;
 128                goto err;
 129        }
 130
 131        omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
 132        omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
 133        omapdss_venc_invert_vid_out_polarity(dssdev,
 134                dssdev->phy.venc.invert_polarity);
 135
 136        r = omapdss_venc_display_enable(dssdev);
 137        if (r)
 138                goto err;
 139
 140        dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
 141
 142        mutex_unlock(&venc_panel.lock);
 143
 144        return 0;
 145err:
 146        mutex_unlock(&venc_panel.lock);
 147
 148        return r;
 149}
 150
 151static void venc_panel_disable(struct omap_dss_device *dssdev)
 152{
 153        dev_dbg(&dssdev->dev, "venc_panel_disable\n");
 154
 155        mutex_lock(&venc_panel.lock);
 156
 157        if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
 158                goto end;
 159
 160        omapdss_venc_display_disable(dssdev);
 161
 162        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 163end:
 164        mutex_unlock(&venc_panel.lock);
 165}
 166
 167static void venc_panel_set_timings(struct omap_dss_device *dssdev,
 168                struct omap_video_timings *timings)
 169{
 170        dev_dbg(&dssdev->dev, "venc_panel_set_timings\n");
 171
 172        mutex_lock(&venc_panel.lock);
 173
 174        omapdss_venc_set_timings(dssdev, timings);
 175        dssdev->panel.timings = *timings;
 176
 177        mutex_unlock(&venc_panel.lock);
 178}
 179
 180static int venc_panel_check_timings(struct omap_dss_device *dssdev,
 181                struct omap_video_timings *timings)
 182{
 183        dev_dbg(&dssdev->dev, "venc_panel_check_timings\n");
 184
 185        return omapdss_venc_check_timings(dssdev, timings);
 186}
 187
 188static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
 189{
 190        dev_dbg(&dssdev->dev, "venc_panel_get_wss\n");
 191
 192        return omapdss_venc_get_wss(dssdev);
 193}
 194
 195static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
 196{
 197        dev_dbg(&dssdev->dev, "venc_panel_set_wss\n");
 198
 199        return omapdss_venc_set_wss(dssdev, wss);
 200}
 201
 202static struct omap_dss_driver venc_driver = {
 203        .probe          = venc_panel_probe,
 204        .remove         = venc_panel_remove,
 205
 206        .enable         = venc_panel_enable,
 207        .disable        = venc_panel_disable,
 208
 209        .get_resolution = omapdss_default_get_resolution,
 210        .get_recommended_bpp = omapdss_default_get_recommended_bpp,
 211
 212        .set_timings    = venc_panel_set_timings,
 213        .check_timings  = venc_panel_check_timings,
 214
 215        .get_wss        = venc_panel_get_wss,
 216        .set_wss        = venc_panel_set_wss,
 217
 218        .driver         = {
 219                .name   = "venc",
 220                .owner  = THIS_MODULE,
 221        },
 222};
 223
 224int venc_panel_init(void)
 225{
 226        return omap_dss_register_driver(&venc_driver);
 227}
 228
 229void venc_panel_exit(void)
 230{
 231        omap_dss_unregister_driver(&venc_driver);
 232}
 233