]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
drivers: staging: imageon configures ADV7611 chip
authorRadhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
Fri, 12 Apr 2013 10:52:59 +0000 (16:22 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Fri, 12 Apr 2013 12:51:51 +0000 (14:51 +0200)
Imageon driver provides platform data for initializing ADV7611
hdmi-in chip.
It configures ADV7611 using V4L2 sub-dev kernel API.
Uses request_firmware API to read EDID from fileystem.
Configured as loadable module and inserted into kernel
when filesystem and mdev(userspace handler) is up.

Signed-off-by: Radhey Shyam Pandey <radheys@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/video/imageon/Kconfig [new file with mode: 0644]
drivers/staging/video/imageon/Makefile [new file with mode: 0644]
drivers/staging/video/imageon/imageon-rx-driver.c [new file with mode: 0644]
drivers/staging/video/imageon/imageon-rx-driver.h [new file with mode: 0644]

index 38fba49471ed6f59033fd663de1ee4a1dcad3726..dcf9effca43e47a36eb81c5b21c4d1e9adaf440f 100644 (file)
@@ -144,4 +144,6 @@ source "drivers/staging/fwserial/Kconfig"
 
 source "drivers/staging/video/axivdma/Kconfig"
 
+source "drivers/staging/video/imageon/Kconfig"
+
 endif # STAGING
index 67356bc588cb29059b96f19813473abefa6a9479..6ffbac4d12468ffcb6d8c9259a51e0614158a14c 100644 (file)
@@ -64,3 +64,4 @@ obj-$(CONFIG_DGRP)            += dgrp/
 obj-$(CONFIG_SB105X)           += sb105x/
 obj-$(CONFIG_FIREWIRE_SERIAL)  += fwserial/
 obj-$(CONFIG_XILINX_VIDEO_IP)   += video/axivdma/
+obj-$(CONFIG_VIDEO_IMAGEON)     += video/imageon/
diff --git a/drivers/staging/video/imageon/Kconfig b/drivers/staging/video/imageon/Kconfig
new file mode 100644 (file)
index 0000000..6bafe68
--- /dev/null
@@ -0,0 +1,11 @@
+config VIDEO_IMAGEON
+       tristate "Imageon card RX support"
+       depends on MEDIA_SUPPORT && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+       select I2C_ALGOBIT
+       select VIDEO_ADV7604
+       ---help---
+         To compile this driver as a module, choose M here: the
+         module will be called imageon-rx.
+         Imageon driver initializes/configures ADV7611 (v4l2 sub device)
+         Configured as a loadable module.
+         It requests EDID using mdev (user-space helper app).
diff --git a/drivers/staging/video/imageon/Makefile b/drivers/staging/video/imageon/Makefile
new file mode 100644 (file)
index 0000000..81ae78b
--- /dev/null
@@ -0,0 +1,3 @@
+imageon-rx-objs := imageon-rx-driver.o
+
+obj-$(CONFIG_VIDEO_IMAGEON) += imageon-rx.o
diff --git a/drivers/staging/video/imageon/imageon-rx-driver.c b/drivers/staging/video/imageon/imageon-rx-driver.c
new file mode 100644 (file)
index 0000000..63d9d18
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Driver for the IMAGEON-FMC board
+ *
+ * Copyright 2012-2013 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * based on cobalt-driver.c
+ *
+ * Licensed under the GPL-2.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of_i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+#include <linux/v4l2-dv-timings.h>
+
+#include <media/adv7604.h>
+#include <media/v4l2-event.h>
+
+#include "imageon-rx-driver.h"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+/* EDID for ADV7611 HDMI receiver */
+#define EDID_SIZE 256
+static u8 edid_data[EDID_SIZE] = {
+       0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+       0x06, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x16, 0x01, 0x03, 0x81, 0x46, 0x27, 0x78,
+       0x0A, 0x32, 0x30, 0xA1, 0x54, 0x52, 0x9E, 0x26,
+       0x0A, 0x49, 0x4B, 0xA3, 0x08, 0x00, 0x81, 0xC0,
+       0x81, 0x00, 0x81, 0x0F, 0x81, 0x40, 0x81, 0x80,
+       0x95, 0x00, 0xB3, 0x00, 0x01, 0x01, 0x02, 0x3A,
+       0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, 0x58, 0x2C,
+       0x45, 0x00, 0xC4, 0x8E, 0x21, 0x00, 0x00, 0x1E,
+       0xA9, 0x1A, 0x00, 0xA0, 0x50, 0x00, 0x16, 0x30,
+       0x30, 0x20, 0x37, 0x00, 0xC4, 0x8E, 0x21, 0x00,
+       0x00, 0x1A, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x46,
+       0x4D, 0x43, 0x2D, 0x49, 0x4D, 0x41, 0x47, 0x45,
+       0x4F, 0x4E, 0x0A, 0x20, 0x00, 0x00, 0x00, 0xFD,
+       0x00, 0x38, 0x4B, 0x20, 0x44, 0x11, 0x00, 0x0A,
+       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x54,
+       0x02, 0x03, 0x1F, 0x71, 0x4B, 0x90, 0x03, 0x04,
+       0x05, 0x12, 0x13, 0x14, 0x1F, 0x20, 0x07, 0x16,
+       0x26, 0x15, 0x07, 0x50, 0x09, 0x07, 0x01, 0x67,
+       0x03, 0x0C, 0x00, 0x10, 0x00, 0x00, 0x1E, 0x01,
+       0x1D, 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20, 0x6E,
+       0x28, 0x55, 0x00, 0xC4, 0x8E, 0x21, 0x00, 0x00,
+       0x1E, 0x01, 0x1D, 0x80, 0x18, 0x71, 0x1C, 0x16,
+       0x20, 0x58, 0x2C, 0x25, 0x00, 0xC4, 0x8E, 0x21,
+       0x00, 0x00, 0x9E, 0x8C, 0x0A, 0xD0, 0x8A, 0x20,
+       0xE0, 0x2D, 0x10, 0x10, 0x3E, 0x96, 0x00, 0xC4,
+       0x8E, 0x21, 0x00, 0x00, 0x18, 0x01, 0x1D, 0x80,
+       0x3E, 0x73, 0x38, 0x2D, 0x40, 0x7E, 0x2C, 0x45,
+       0x80, 0xC4, 0x8E, 0x21, 0x00, 0x00, 0x1E, 0x1A,
+       0x36, 0x80, 0xA0, 0x70, 0x38, 0x1F, 0x40, 0x30,
+       0x20, 0x25, 0x00, 0xC4, 0x8E, 0x21, 0x00, 0x00,
+       0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+};
+
+static void imageon_rx_notify(struct v4l2_subdev *sd, unsigned int notification,
+       void *arg)
+{
+       /* pr_err("%s\n",__func__); */
+
+       struct imageon_rx *imageon_rx = to_imageon_rx(sd->v4l2_dev);
+       long hotplug = (long)arg;
+
+       switch (notification) {
+       case ADV7604_HOTPLUG:
+               gpio_set_value_cansleep(imageon_rx->hotplug_gpio, hotplug);
+               break;
+       default:
+               break;
+       }
+}
+
+static int imageon_rx_subdevs_init(struct imageon_rx *imageon_rx)
+{
+       static struct adv7604_platform_data adv7611_pdata = {
+               .disable_pwrdnb = 1,
+               .op_ch_sel = ADV7604_OP_CH_SEL_RGB,
+               .blank_data = 1,
+               .op_656_range = 1,
+               .rgb_out = 0,
+               .alt_data_sat = 1,
+               .op_format_sel = ADV7604_OP_FORMAT_SEL_SDR_ITU656_16,
+               .int1_config = ADV7604_INT1_CONFIG_OPEN_DRAIN,
+               .connector_hdmi = 1,
+               .insert_av_codes = 1,
+               .i2c_cec = 0x40,
+               .i2c_infoframe = 0x3e,
+               .i2c_afe = 0x26,
+               .i2c_repeater = 0x32,
+               .i2c_edid = 0x36,
+               .i2c_hdmi = 0x34,
+               .i2c_cp = 0x22,
+       };
+       static struct i2c_board_info adv7611_info = {
+               .type = "adv7611",
+               .addr = 0x4c,
+               .platform_data = &adv7611_pdata,
+       };
+       struct v4l2_subdev_edid edid = {
+               .pad = 0,
+               .start_block = 0,
+               .blocks = 2,
+               .edid = imageon_rx->edid_data,
+       };
+
+       struct imageon_rx_stream *s = &imageon_rx->stream;
+
+       s->sd_adv7611 = v4l2_i2c_new_subdev_board(&imageon_rx->v4l2_dev,
+               s->i2c_adap, &adv7611_info, NULL);
+       if (!s->sd_adv7611)
+               return -ENODEV;
+
+       v4l2_subdev_call(s->sd_adv7611, pad, set_edid, &edid);
+       return v4l2_subdev_call(s->sd_adv7611, video,
+               s_routing, ADV7604_MODE_HDMI, 0, 0);
+}
+
+static int imageon_rx_load_edid(struct platform_device *pdev,
+       struct imageon_rx *imageon_rx)
+{
+       const struct firmware *fw;
+       int ret;
+
+       ret = request_firmware(&fw, "adv7611_edid.bin", &pdev->dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to load firmware: %d\n", ret);
+               /*Using default EDID setting in case of failure */
+               dev_err(&pdev->dev, "Loading default EDID setting\n");
+               /*Copy EDID data */
+               memcpy(imageon_rx->edid_data, edid_data, EDID_SIZE);
+       } else {
+
+               if (fw->size > 256) {
+                       dev_err(&pdev->dev, "EDID firmware data too large.\n");
+                       release_firmware(fw);
+                       return -EINVAL;
+               }
+
+               memcpy(imageon_rx->edid_data, fw->data, fw->size);
+
+               release_firmware(fw);
+       }
+
+       return 0;
+}
+
+static int imageon_rx_probe(struct platform_device *pdev)
+{
+       struct device_node *of_node;
+       struct i2c_adapter *adap;
+       struct imageon_rx *imageon_rx;
+       int ret;
+
+       of_node = of_parse_phandle(pdev->dev.of_node, "slave_adapter", 0);
+       if (!of_node)
+               return -ENXIO;
+
+       adap = of_find_i2c_adapter_by_node(of_node);
+       of_node_put(of_node);
+       if (!adap)
+               return -EPROBE_DEFER;
+
+       imageon_rx =
+       devm_kzalloc(&pdev->dev, sizeof(struct imageon_rx), GFP_KERNEL);
+       if (imageon_rx == NULL) {
+               dev_err(&pdev->dev, "Failed to allocate device\n");
+               ret = -ENOMEM;
+               goto err_i2c_put_adapter;
+       }
+
+       imageon_rx->hotplug_gpio =
+       of_get_named_gpio(pdev->dev.of_node, "hpd-gpio", 0);
+       if (!gpio_is_valid(imageon_rx->hotplug_gpio))
+               return imageon_rx->hotplug_gpio;
+
+
+       ret = devm_gpio_request_one(&pdev->dev,
+               imageon_rx->hotplug_gpio, GPIOF_OUT_INIT_LOW, "HPD");
+       if (ret < 0)
+               return ret;
+       imageon_rx->stream.i2c_adap = adap;
+
+
+       ret = imageon_rx_load_edid(pdev, imageon_rx);
+       if (ret)
+               goto err_i2c_put_adapter;
+
+       ret = v4l2_device_register(&pdev->dev, &imageon_rx->v4l2_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to register card: %d\n", ret);
+               goto err_device_unregister;
+       }
+       snprintf(imageon_rx->v4l2_dev.name, sizeof(imageon_rx->v4l2_dev.name),
+               "imageon_rx");
+
+       imageon_rx->v4l2_dev.notify = imageon_rx_notify;
+
+       ret = imageon_rx_subdevs_init(imageon_rx);
+       if (ret)
+               goto err_device_unregister;
+
+       ret = v4l2_device_register_subdev_nodes(&imageon_rx->v4l2_dev);
+       if (ret)
+               goto err_device_unregister;
+
+       video_set_drvdata(&imageon_rx->stream.vdev, imageon_rx);
+
+       return 0;
+
+err_device_unregister:
+       v4l2_device_unregister(&imageon_rx->v4l2_dev);
+err_i2c_put_adapter:
+       i2c_put_adapter(adap);
+       return ret;
+}
+
+static int imageon_rx_remove(struct platform_device *pdev)
+{
+       struct imageon_rx *imageon_rx = platform_get_drvdata(pdev);
+
+       v4l2_device_unregister(&imageon_rx->v4l2_dev);
+       i2c_put_adapter(imageon_rx->stream.i2c_adap);
+
+       return 0;
+}
+
+static const struct of_device_id imageon_rx_of_match[] = {
+       { .compatible = "xlnx,imageon-rx", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, imageon_rx_of_match);
+
+static struct platform_driver imageon_rx_driver = {
+       .driver = {
+               .name = "imageon-rx",
+               .owner = THIS_MODULE,
+               .of_match_table = imageon_rx_of_match,
+       },
+       .probe = imageon_rx_probe,
+       .remove = imageon_rx_remove,
+};
+module_platform_driver(imageon_rx_driver);
diff --git a/drivers/staging/video/imageon/imageon-rx-driver.h b/drivers/staging/video/imageon/imageon-rx-driver.h
new file mode 100644 (file)
index 0000000..7c40a06
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  imageon_rx driver internal defines and structures
+ *
+ *  Derived from cx18-driver.h
+ *
+ *  Copyright 2011 Tandberg Telecom AS.  All rights reserved.
+ *
+ *  This program is free software; you may redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ *  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ *  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ */
+
+#ifndef IMAGEON_RX_DRIVER_H
+#define IMAGEON_RX_DRIVER_H
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/amba/xilinx_dma.h>
+#include <linux/debugfs.h>
+
+#include <linux/i2c.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/videobuf2-dma-sg.h>
+
+struct imageon_rx_stream {
+       struct video_device vdev;
+       struct media_pad pad;
+       struct vb2_queue q;
+       struct i2c_adapter *i2c_adap;
+       struct v4l2_subdev *sd_adv7611;
+       struct mutex lock;
+       spinlock_t spinlock;
+       u32 input;
+       u32 width, height, bpp, pack_fmt;
+       u32 stride;
+
+       struct dma_chan *chan;
+       struct xilinx_vdma_config dma_config;
+
+       struct list_head queued_buffers;
+};
+
+/* Struct to hold info about imageon_rx cards */
+struct imageon_rx {
+       struct v4l2_device v4l2_dev;
+       struct vb2_alloc_ctx    *alloc_ctx;
+
+       /* device nodes */
+       struct media_device mdev;
+       struct imageon_rx_stream stream;
+
+       int hotplug_gpio;
+
+       void __iomem *base;
+
+       u8 edid_data[256];
+};
+
+static inline struct imageon_rx *to_imageon_rx(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct imageon_rx, v4l2_dev);
+}
+
+static inline struct imageon_rx_stream
+                       *imageon_rx_file_to_stream(struct file *file)
+{
+       struct imageon_rx *imageon_rx = video_drvdata(file);
+       return &imageon_rx->stream;
+}
+
+static inline struct imageon_rx *imageon_rx_stream_to_imageon_rx(
+       struct imageon_rx_stream *s)
+{
+       return container_of(s, struct imageon_rx, stream);
+}
+
+int imageon_rx_nodes_register(struct imageon_rx *imageon_rx);
+
+#define IMAGEON_RX_BYTES_PER_PIXEL_YUYV 4
+#define IMAGEON_RX_BYTES_PER_PIXEL_RGB32 4
+
+enum {
+       IMAGEON_RX_VID_PACK_FMT_RGB32,
+/*
+       IMAGEON_RX_VID_PACK_FMT_YUYV,*/
+};
+
+#endif