sdo_drv.c revision cf48f56c27ecfe94fbea363db6e8e0bacbd525ed
19a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski/* 29a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski * Samsung Standard Definition Output (SDO) driver 39a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski * 49a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. 59a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski * 69a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski * Tomasz Stanislawski, <t.stanislaws@samsung.com> 79a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski * 89a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski * This program is free software; you can redistribute it and/or modify 99a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski * it under the terms of the GNU General Public License as published 109a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski * by the Free Software Foundiation. either version 2 of the License, 119a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski * or (at your option) any later version 129a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski */ 139a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 149a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/clk.h> 159a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/delay.h> 169a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/kernel.h> 179a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/module.h> 189a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/interrupt.h> 199a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/io.h> 209a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/irq.h> 219a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/platform_device.h> 229a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/pm_runtime.h> 239a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/regulator/consumer.h> 249a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <linux/slab.h> 259a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 269a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include <media/v4l2-subdev.h> 279a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 289a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#include "regs-sdo.h" 299a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 309a498400fede652a5ada51e74ae47bba99c7ed07Tomasz StanislawskiMODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>"); 319a498400fede652a5ada51e74ae47bba99c7ed07Tomasz StanislawskiMODULE_DESCRIPTION("Samsung Standard Definition Output (SDO)"); 329a498400fede652a5ada51e74ae47bba99c7ed07Tomasz StanislawskiMODULE_LICENSE("GPL"); 339a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 349a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#define SDO_DEFAULT_STD V4L2_STD_PAL 359a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 369a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistruct sdo_format { 379a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski v4l2_std_id id; 389a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* all modes are 720 pixels wide */ 399a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski unsigned int height; 409a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski unsigned int cookie; 419a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 429a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 439a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistruct sdo_device { 449a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** pointer to device parent */ 459a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct device *dev; 469a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** base address of SDO registers */ 479a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski void __iomem *regs; 489a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** SDO interrupt */ 499a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski unsigned int irq; 509a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** DAC source clock */ 519a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct clk *sclk_dac; 529a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** DAC clock */ 539a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct clk *dac; 549a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** DAC physical interface */ 559a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct clk *dacphy; 569a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** clock for control of VPLL */ 579a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct clk *fout_vpll; 589a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** regulator for SDO IP power */ 599a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct regulator *vdac; 609a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** regulator for SDO plug detection */ 619a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct regulator *vdet; 629a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** subdev used as device interface */ 639a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct v4l2_subdev sd; 649a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** current format */ 659a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski const struct sdo_format *fmt; 669a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 679a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 689a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic inline struct sdo_device *sd_to_sdev(struct v4l2_subdev *sd) 699a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 709a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return container_of(sd, struct sdo_device, sd); 719a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 729a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 739a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic inline 749a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskivoid sdo_write_mask(struct sdo_device *sdev, u32 reg_id, u32 value, u32 mask) 759a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 769a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski u32 old = readl(sdev->regs + reg_id); 779a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski value = (value & mask) | (old & ~mask); 789a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski writel(value, sdev->regs + reg_id); 799a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 809a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 819a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic inline 829a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskivoid sdo_write(struct sdo_device *sdev, u32 reg_id, u32 value) 839a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 849a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski writel(value, sdev->regs + reg_id); 859a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 869a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 879a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic inline 889a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskiu32 sdo_read(struct sdo_device *sdev, u32 reg_id) 899a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 909a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return readl(sdev->regs + reg_id); 919a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 929a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 939a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic irqreturn_t sdo_irq_handler(int irq, void *dev_data) 949a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 959a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = dev_data; 969a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 979a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* clear interrupt */ 989a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_IRQ, ~0, SDO_VSYNC_IRQ_PEND); 999a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return IRQ_HANDLED; 1009a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1019a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1029a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic void sdo_reg_debug(struct sdo_device *sdev) 1039a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1049a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#define DBGREG(reg_id) \ 1059a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(sdev->dev, #reg_id " = %08x\n", \ 1069a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_read(sdev, reg_id)) 1079a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1089a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_CLKCON); 1099a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_CONFIG); 1109a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_VBI); 1119a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_DAC); 1129a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_IRQ); 1139a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_IRQMASK); 1149a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_VERSION); 1159a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1169a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1179a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct sdo_format sdo_format[] = { 1189a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_PAL_N, .height = 576, .cookie = SDO_PAL_N }, 1199a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_PAL_Nc, .height = 576, .cookie = SDO_PAL_NC }, 1209a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_PAL_M, .height = 480, .cookie = SDO_PAL_M }, 1219a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_PAL_60, .height = 480, .cookie = SDO_PAL_60 }, 1229a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_NTSC_443, .height = 480, .cookie = SDO_NTSC_443 }, 1239a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_PAL, .height = 576, .cookie = SDO_PAL_BGHID }, 1249a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_NTSC_M, .height = 480, .cookie = SDO_NTSC_M }, 1259a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 1269a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1279a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct sdo_format *sdo_find_format(v4l2_std_id id) 1289a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1299a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski int i; 1309a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski for (i = 0; i < ARRAY_SIZE(sdo_format); ++i) 1319a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (sdo_format[i].id & id) 1329a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return &sdo_format[i]; 1339a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return NULL; 1349a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1359a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1369a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_g_tvnorms_output(struct v4l2_subdev *sd, v4l2_std_id *std) 1379a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1389a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski *std = V4L2_STD_NTSC_M | V4L2_STD_PAL_M | V4L2_STD_PAL | 1399a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | 1409a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski V4L2_STD_NTSC_443 | V4L2_STD_PAL_60; 1419a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 1429a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1439a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1449a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) 1459a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1469a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 1479a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski const struct sdo_format *fmt; 1489a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski fmt = sdo_find_format(std); 1499a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (fmt == NULL) 1509a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return -EINVAL; 1519a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->fmt = fmt; 1529a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 1539a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1549a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1559a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_g_std_output(struct v4l2_subdev *sd, v4l2_std_id *std) 1569a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1579a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski *std = sd_to_sdev(sd)->fmt->id; 1589a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 1599a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1609a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1619a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_g_mbus_fmt(struct v4l2_subdev *sd, 1629a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct v4l2_mbus_framefmt *fmt) 1639a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1649a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 1659a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1669a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (!sdev->fmt) 1679a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return -ENXIO; 1689a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* all modes are 720 pixels wide */ 1699a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski fmt->width = 720; 1709a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski fmt->height = sdev->fmt->height; 1719a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski fmt->code = V4L2_MBUS_FMT_FIXED; 1729a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski fmt->field = V4L2_FIELD_INTERLACED; 1730689133b7fadd2e10f4bddca36c895223a541c6cTomasz Stanislawski fmt->colorspace = V4L2_COLORSPACE_JPEG; 1749a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 1759a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1769a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1779a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_s_power(struct v4l2_subdev *sd, int on) 1789a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1799a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 1809a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct device *dev = sdev->dev; 1819a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski int ret; 1829a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1839a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "sdo_s_power(%d)\n", on); 1849a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1859a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (on) 1869a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = pm_runtime_get_sync(dev); 1879a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski else 1889a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = pm_runtime_put_sync(dev); 1899a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1909a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* only values < 0 indicate errors */ 1919a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return IS_ERR_VALUE(ret) ? ret : 0; 1929a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1939a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1949a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_streamon(struct sdo_device *sdev) 1959a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1969a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* set proper clock for Timing Generator */ 1979a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_set_rate(sdev->fout_vpll, 54000000); 1989a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(sdev->dev, "fout_vpll.rate = %lu\n", 1999a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_get_rate(sdev->fout_vpll)); 2009a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* enable clock in SDO */ 2019a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_CLOCK_ON); 2029a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_enable(sdev->dacphy); 2039a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* enable DAC */ 2049a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_DAC, ~0, SDO_POWER_ON_DAC); 2059a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_reg_debug(sdev); 2069a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 2079a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 2089a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2099a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_streamoff(struct sdo_device *sdev) 2109a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 2119a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski int tries; 2129a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2139a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_DAC, 0, SDO_POWER_ON_DAC); 2149a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_disable(sdev->dacphy); 2159a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_CLOCK_ON); 2169a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski for (tries = 100; tries; --tries) { 2179a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (sdo_read(sdev, SDO_CLKCON) & SDO_TVOUT_CLOCK_READY) 2189a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski break; 2199a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski mdelay(1); 2209a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 2219a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (tries == 0) 2229a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(sdev->dev, "failed to stop streaming\n"); 2239a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return tries ? 0 : -EIO; 2249a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 2259a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2269a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_s_stream(struct v4l2_subdev *sd, int on) 2279a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 2289a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 2299a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return on ? sdo_streamon(sdev) : sdo_streamoff(sdev); 2309a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 2319a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2329a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct v4l2_subdev_core_ops sdo_sd_core_ops = { 2339a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .s_power = sdo_s_power, 2349a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 2359a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2369a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct v4l2_subdev_video_ops sdo_sd_video_ops = { 2379a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .s_std_output = sdo_s_std_output, 2389a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .g_std_output = sdo_g_std_output, 2399a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .g_tvnorms_output = sdo_g_tvnorms_output, 2409a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .g_mbus_fmt = sdo_g_mbus_fmt, 2419a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .s_stream = sdo_s_stream, 2429a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 2439a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2449a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct v4l2_subdev_ops sdo_sd_ops = { 2459a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .core = &sdo_sd_core_ops, 2469a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .video = &sdo_sd_video_ops, 2479a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 2489a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2499a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_runtime_suspend(struct device *dev) 2509a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 2519a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct v4l2_subdev *sd = dev_get_drvdata(dev); 2529a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 2539a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2549a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "suspend\n"); 2559a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski regulator_disable(sdev->vdet); 2569a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski regulator_disable(sdev->vdac); 2579a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_disable(sdev->sclk_dac); 2589a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 2599a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 2609a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2619a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_runtime_resume(struct device *dev) 2629a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 2639a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct v4l2_subdev *sd = dev_get_drvdata(dev); 2649a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 2659a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2669a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "resume\n"); 2679a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_enable(sdev->sclk_dac); 2689a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski regulator_enable(sdev->vdac); 2699a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski regulator_enable(sdev->vdet); 2709a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2719a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* software reset */ 2729a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_SW_RESET); 2739a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski mdelay(10); 2749a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_SW_RESET); 2759a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2769a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* setting TV mode */ 2779a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CONFIG, sdev->fmt->cookie, SDO_STANDARD_MASK); 2789a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* XXX: forcing interlaced mode using undocumented bit */ 2799a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CONFIG, 0, SDO_PROGRESSIVE); 2809a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* turn all VBI off */ 2819a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_VBI, 0, SDO_CVBS_WSS_INS | 2829a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski SDO_CVBS_CLOSED_CAPTION_MASK); 2839a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* turn all post processing off */ 2849a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CCCON, ~0, SDO_COMPENSATION_BHS_ADJ_OFF | 2859a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski SDO_COMPENSATION_CVBS_COMP_OFF); 2869a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_reg_debug(sdev); 2879a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 2889a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 2899a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2909a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct dev_pm_ops sdo_pm_ops = { 2919a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .runtime_suspend = sdo_runtime_suspend, 2929a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .runtime_resume = sdo_runtime_resume, 2939a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 2949a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2959a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int __devinit sdo_probe(struct platform_device *pdev) 2969a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 2979a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct device *dev = &pdev->dev; 2989a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev; 2999a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct resource *res; 3009a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski int ret = 0; 3019a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct clk *sclk_vpll; 3029a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3039a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "probe start\n"); 304e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall sdev = devm_kzalloc(&pdev->dev, sizeof *sdev, GFP_KERNEL); 3059a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (!sdev) { 3069a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "not enough memory.\n"); 3079a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = -ENOMEM; 3089a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail; 3099a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3109a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->dev = dev; 3119a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3129a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* mapping registers */ 3139a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 3149a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (res == NULL) { 3159a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "get memory resource failed.\n"); 3169a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = -ENXIO; 317e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall goto fail; 3189a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3199a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 320e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall sdev->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 3219a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (sdev->regs == NULL) { 3229a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "register mapping failed.\n"); 3239a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = -ENXIO; 324e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall goto fail; 3259a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3269a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3279a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* acquiring interrupt */ 3289a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 3299a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (res == NULL) { 3309a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "get interrupt resource failed.\n"); 3319a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = -ENXIO; 332e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall goto fail; 3339a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 334e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall ret = devm_request_irq(&pdev->dev, res->start, sdo_irq_handler, 0, 335e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall "s5p-sdo", sdev); 3369a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (ret) { 3379a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "request interrupt failed.\n"); 338e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall goto fail; 3399a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3409a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->irq = res->start; 3419a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3429a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* acquire clocks */ 3439a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->sclk_dac = clk_get(dev, "sclk_dac"); 344cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->sclk_dac)) { 3459a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get clock 'sclk_dac'\n"); 346cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->sclk_dac); 347e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall goto fail; 3489a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3499a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->dac = clk_get(dev, "dac"); 350cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->dac)) { 3519a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get clock 'dac'\n"); 352cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->dac); 3539a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail_sclk_dac; 3549a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3559a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->dacphy = clk_get(dev, "dacphy"); 356cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->dacphy)) { 3579a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get clock 'dacphy'\n"); 358cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->dacphy); 3599a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail_dac; 3609a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3619a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sclk_vpll = clk_get(dev, "sclk_vpll"); 362cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sclk_vpll)) { 3639a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get clock 'sclk_vpll'\n"); 364cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sclk_vpll); 3659a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail_dacphy; 3669a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3679a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_set_parent(sdev->sclk_dac, sclk_vpll); 3689a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sclk_vpll); 3699a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->fout_vpll = clk_get(dev, "fout_vpll"); 370cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->fout_vpll)) { 3719a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get clock 'fout_vpll'\n"); 372cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->fout_vpll); 3739a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail_dacphy; 3749a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3759a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "fout_vpll.rate = %lu\n", clk_get_rate(sclk_vpll)); 3769a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3779a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* acquire regulator */ 37800d98c1bd6fe93de6db6a99ed25b4b7d96a402ecSachin Kamat sdev->vdac = devm_regulator_get(dev, "vdd33a_dac"); 379cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->vdac)) { 3809a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get regulator 'vdac'\n"); 381cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->vdac); 3829a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail_fout_vpll; 3839a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 38400d98c1bd6fe93de6db6a99ed25b4b7d96a402ecSachin Kamat sdev->vdet = devm_regulator_get(dev, "vdet"); 385cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->vdet)) { 3869a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get regulator 'vdet'\n"); 387cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->vdet); 38800d98c1bd6fe93de6db6a99ed25b4b7d96a402ecSachin Kamat goto fail_fout_vpll; 3899a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3909a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3919a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* enable gate for dac clock, because mixer uses it */ 3929a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_enable(sdev->dac); 3939a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3949a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* configure power management */ 3959a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski pm_runtime_enable(dev); 3969a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3979a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* configuration of interface subdevice */ 3989a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski v4l2_subdev_init(&sdev->sd, &sdo_sd_ops); 3999a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->sd.owner = THIS_MODULE; 4009a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski strlcpy(sdev->sd.name, "s5p-sdo", sizeof sdev->sd.name); 4019a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4029a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* set default format */ 4039a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->fmt = sdo_find_format(SDO_DEFAULT_STD); 4049a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski BUG_ON(sdev->fmt == NULL); 4059a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4069a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* keeping subdev in device's private for use by other drivers */ 4079a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_set_drvdata(dev, &sdev->sd); 4089a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4099a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "probe succeeded\n"); 4109a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 4119a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4129a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskifail_fout_vpll: 4139a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->fout_vpll); 4149a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskifail_dacphy: 4159a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->dacphy); 4169a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskifail_dac: 4179a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->dac); 4189a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskifail_sclk_dac: 4199a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->sclk_dac); 4209a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskifail: 4219a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "probe failed\n"); 4229a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return ret; 4239a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 4249a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4259a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int __devexit sdo_remove(struct platform_device *pdev) 4269a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 4279a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev); 4289a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 4299a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4309a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski pm_runtime_disable(&pdev->dev); 4319a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_disable(sdev->dac); 4329a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->fout_vpll); 4339a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->dacphy); 4349a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->dac); 4359a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->sclk_dac); 4369a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4379a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(&pdev->dev, "remove successful\n"); 4389a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 4399a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 4409a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4419a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic struct platform_driver sdo_driver __refdata = { 4429a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .probe = sdo_probe, 4439a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .remove = __devexit_p(sdo_remove), 4449a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .driver = { 4459a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .name = "s5p-sdo", 4469a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .owner = THIS_MODULE, 4479a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .pm = &sdo_pm_ops, 4489a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 4499a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 4509a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4511d6629b1561ad34a6e6d17ece00bd65e1bab3724Axel Linmodule_platform_driver(sdo_driver); 452