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; 580495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk /** vpll rate before sdo stream was on */ 590495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk unsigned long vpll_rate; 609a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** regulator for SDO IP power */ 619a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct regulator *vdac; 629a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** regulator for SDO plug detection */ 639a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct regulator *vdet; 649a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** subdev used as device interface */ 659a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct v4l2_subdev sd; 669a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /** current format */ 679a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski const struct sdo_format *fmt; 689a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 699a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 709a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic inline struct sdo_device *sd_to_sdev(struct v4l2_subdev *sd) 719a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 729a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return container_of(sd, struct sdo_device, sd); 739a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 749a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 759a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic inline 769a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskivoid sdo_write_mask(struct sdo_device *sdev, u32 reg_id, u32 value, u32 mask) 779a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 789a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski u32 old = readl(sdev->regs + reg_id); 799a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski value = (value & mask) | (old & ~mask); 809a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski writel(value, sdev->regs + reg_id); 819a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 829a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 839a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic inline 849a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskivoid sdo_write(struct sdo_device *sdev, u32 reg_id, u32 value) 859a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 869a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski writel(value, sdev->regs + reg_id); 879a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 889a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 899a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic inline 909a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskiu32 sdo_read(struct sdo_device *sdev, u32 reg_id) 919a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 929a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return readl(sdev->regs + reg_id); 939a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 949a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 959a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic irqreturn_t sdo_irq_handler(int irq, void *dev_data) 969a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 979a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = dev_data; 989a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 999a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* clear interrupt */ 1009a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_IRQ, ~0, SDO_VSYNC_IRQ_PEND); 1019a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return IRQ_HANDLED; 1029a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1039a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1049a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic void sdo_reg_debug(struct sdo_device *sdev) 1059a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1069a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski#define DBGREG(reg_id) \ 1079a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(sdev->dev, #reg_id " = %08x\n", \ 1089a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_read(sdev, reg_id)) 1099a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1109a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_CLKCON); 1119a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_CONFIG); 1129a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_VBI); 1139a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_DAC); 1149a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_IRQ); 1159a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_IRQMASK); 1169a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski DBGREG(SDO_VERSION); 1179a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1189a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1199a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct sdo_format sdo_format[] = { 1209a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_PAL_N, .height = 576, .cookie = SDO_PAL_N }, 1219a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_PAL_Nc, .height = 576, .cookie = SDO_PAL_NC }, 1229a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_PAL_M, .height = 480, .cookie = SDO_PAL_M }, 1239a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_PAL_60, .height = 480, .cookie = SDO_PAL_60 }, 1249a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_NTSC_443, .height = 480, .cookie = SDO_NTSC_443 }, 1259a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_PAL, .height = 576, .cookie = SDO_PAL_BGHID }, 1269a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski { V4L2_STD_NTSC_M, .height = 480, .cookie = SDO_NTSC_M }, 1279a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 1289a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1299a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct sdo_format *sdo_find_format(v4l2_std_id id) 1309a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1319a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski int i; 1329a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski for (i = 0; i < ARRAY_SIZE(sdo_format); ++i) 1339a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (sdo_format[i].id & id) 1349a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return &sdo_format[i]; 1359a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return NULL; 1369a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1379a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1389a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_g_tvnorms_output(struct v4l2_subdev *sd, v4l2_std_id *std) 1399a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1409a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski *std = V4L2_STD_NTSC_M | V4L2_STD_PAL_M | V4L2_STD_PAL | 1419a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | 1429a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski V4L2_STD_NTSC_443 | V4L2_STD_PAL_60; 1439a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 1449a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1459a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1469a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) 1479a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1489a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 1499a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski const struct sdo_format *fmt; 1509a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski fmt = sdo_find_format(std); 1519a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (fmt == NULL) 1529a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return -EINVAL; 1539a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->fmt = fmt; 1549a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 1559a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1569a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1579a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_g_std_output(struct v4l2_subdev *sd, v4l2_std_id *std) 1589a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1599a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski *std = sd_to_sdev(sd)->fmt->id; 1609a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 1619a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1629a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1639a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_g_mbus_fmt(struct v4l2_subdev *sd, 1649a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct v4l2_mbus_framefmt *fmt) 1659a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1669a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 1679a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1689a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (!sdev->fmt) 1699a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return -ENXIO; 1709a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* all modes are 720 pixels wide */ 1719a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski fmt->width = 720; 1729a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski fmt->height = sdev->fmt->height; 1739a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski fmt->code = V4L2_MBUS_FMT_FIXED; 1749a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski fmt->field = V4L2_FIELD_INTERLACED; 1750689133b7fadd2e10f4bddca36c895223a541c6cTomasz Stanislawski fmt->colorspace = V4L2_COLORSPACE_JPEG; 1769a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 1779a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1789a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1799a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_s_power(struct v4l2_subdev *sd, int on) 1809a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1819a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 1829a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct device *dev = sdev->dev; 1839a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski int ret; 1849a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1859a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "sdo_s_power(%d)\n", on); 1869a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1879a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (on) 1889a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = pm_runtime_get_sync(dev); 1899a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski else 1909a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = pm_runtime_put_sync(dev); 1919a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1929a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* only values < 0 indicate errors */ 193d8e8b40c067c3242b32ebe835f6bc6247fd67454Mauro Carvalho Chehab return ret < 0 ? ret : 0; 1949a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 1959a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 1969a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_streamon(struct sdo_device *sdev) 1979a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 1980495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk int ret; 1990495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk 2009a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* set proper clock for Timing Generator */ 2010495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk sdev->vpll_rate = clk_get_rate(sdev->fout_vpll); 2020495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk ret = clk_set_rate(sdev->fout_vpll, 54000000); 2030495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk if (ret < 0) { 2040495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk dev_err(sdev->dev, "Failed to set vpll rate\n"); 2050495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk return ret; 2060495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk } 2079a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(sdev->dev, "fout_vpll.rate = %lu\n", 2089a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_get_rate(sdev->fout_vpll)); 2099a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* enable clock in SDO */ 2109a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_CLOCK_ON); 211a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk ret = clk_prepare_enable(sdev->dacphy); 2120495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk if (ret < 0) { 213a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk dev_err(sdev->dev, "clk_prepare_enable(dacphy) failed\n"); 2140495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk goto fail; 2150495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk } 2169a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* enable DAC */ 2179a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_DAC, ~0, SDO_POWER_ON_DAC); 2189a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_reg_debug(sdev); 2199a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 2200495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk 2210495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczukfail: 2220495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_CLOCK_ON); 2230495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk clk_set_rate(sdev->fout_vpll, sdev->vpll_rate); 2240495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk return ret; 2259a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 2269a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2279a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_streamoff(struct sdo_device *sdev) 2289a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 2299a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski int tries; 2309a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2319a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_DAC, 0, SDO_POWER_ON_DAC); 232a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk clk_disable_unprepare(sdev->dacphy); 2339a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_CLOCK_ON); 2349a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski for (tries = 100; tries; --tries) { 2359a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (sdo_read(sdev, SDO_CLKCON) & SDO_TVOUT_CLOCK_READY) 2369a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski break; 2379a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski mdelay(1); 2389a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 2399a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (tries == 0) 2409a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(sdev->dev, "failed to stop streaming\n"); 2410495d405f319171ac1cb6276019fc49a382fa295Mateusz Krawczuk clk_set_rate(sdev->fout_vpll, sdev->vpll_rate); 2429a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return tries ? 0 : -EIO; 2439a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 2449a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2459a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_s_stream(struct v4l2_subdev *sd, int on) 2469a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 2479a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 2489a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return on ? sdo_streamon(sdev) : sdo_streamoff(sdev); 2499a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 2509a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2519a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct v4l2_subdev_core_ops sdo_sd_core_ops = { 2529a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .s_power = sdo_s_power, 2539a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 2549a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2559a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct v4l2_subdev_video_ops sdo_sd_video_ops = { 2569a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .s_std_output = sdo_s_std_output, 2579a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .g_std_output = sdo_g_std_output, 2589a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .g_tvnorms_output = sdo_g_tvnorms_output, 2599a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .g_mbus_fmt = sdo_g_mbus_fmt, 2609a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .s_stream = sdo_s_stream, 2619a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 2629a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2639a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct v4l2_subdev_ops sdo_sd_ops = { 2649a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .core = &sdo_sd_core_ops, 2659a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .video = &sdo_sd_video_ops, 2669a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 2679a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2689a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_runtime_suspend(struct device *dev) 2699a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 2709a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct v4l2_subdev *sd = dev_get_drvdata(dev); 2719a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 2729a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2739a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "suspend\n"); 2749a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski regulator_disable(sdev->vdet); 2759a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski regulator_disable(sdev->vdac); 276a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk clk_disable_unprepare(sdev->sclk_dac); 2779a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 2789a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 2799a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2809a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic int sdo_runtime_resume(struct device *dev) 2819a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 2829a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct v4l2_subdev *sd = dev_get_drvdata(dev); 2839a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 284d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki int ret; 2859a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 2869a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "resume\n"); 287d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki 288a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk ret = clk_prepare_enable(sdev->sclk_dac); 289d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki if (ret < 0) 290d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki return ret; 291d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki 292d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki ret = regulator_enable(sdev->vdac); 293d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki if (ret < 0) 294d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki goto dac_clk_dis; 295d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki 296d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki ret = regulator_enable(sdev->vdet); 297d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki if (ret < 0) 298d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki goto vdac_r_dis; 2999a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3009a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* software reset */ 3019a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_SW_RESET); 3029a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski mdelay(10); 3039a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_SW_RESET); 3049a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3059a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* setting TV mode */ 3069a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CONFIG, sdev->fmt->cookie, SDO_STANDARD_MASK); 3079a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* XXX: forcing interlaced mode using undocumented bit */ 3089a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CONFIG, 0, SDO_PROGRESSIVE); 3099a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* turn all VBI off */ 3109a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_VBI, 0, SDO_CVBS_WSS_INS | 3119a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski SDO_CVBS_CLOSED_CAPTION_MASK); 3129a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* turn all post processing off */ 3139a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_write_mask(sdev, SDO_CCCON, ~0, SDO_COMPENSATION_BHS_ADJ_OFF | 3149a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski SDO_COMPENSATION_CVBS_COMP_OFF); 3159a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdo_reg_debug(sdev); 3169a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 317d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki 318d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrockivdac_r_dis: 319d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki regulator_disable(sdev->vdac); 320d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrockidac_clk_dis: 321a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk clk_disable_unprepare(sdev->sclk_dac); 322d285837eaf5e363ac0ab1bf6deb110e007325949Sylwester Nawrocki return ret; 3239a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 3249a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3259a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic const struct dev_pm_ops sdo_pm_ops = { 3269a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .runtime_suspend = sdo_runtime_suspend, 3279a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .runtime_resume = sdo_runtime_resume, 3289a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 3299a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3304c62e9764ab403d42f9b8871b1241fe7812f19d4Greg Kroah-Hartmanstatic int sdo_probe(struct platform_device *pdev) 3319a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 3329a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct device *dev = &pdev->dev; 3339a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev; 3349a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct resource *res; 3359a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski int ret = 0; 3369a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct clk *sclk_vpll; 3379a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3389a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "probe start\n"); 33980f0dee21c7ec39f76f90548c9f08a0e7ec9b3faSachin Kamat sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL); 3409a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (!sdev) { 3419a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "not enough memory.\n"); 3429a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = -ENOMEM; 3439a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail; 3449a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3459a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->dev = dev; 3469a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3479a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* mapping registers */ 3489a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 3499a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (res == NULL) { 3509a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "get memory resource failed.\n"); 3519a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = -ENXIO; 352e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall goto fail; 3539a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3549a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 355e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall sdev->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 3569a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (sdev->regs == NULL) { 3579a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "register mapping failed.\n"); 3589a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = -ENXIO; 359e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall goto fail; 3609a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3619a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3629a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* acquiring interrupt */ 3639a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 3649a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (res == NULL) { 3659a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "get interrupt resource failed.\n"); 3669a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski ret = -ENXIO; 367e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall goto fail; 3689a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 369e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall ret = devm_request_irq(&pdev->dev, res->start, sdo_irq_handler, 0, 370e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall "s5p-sdo", sdev); 3719a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski if (ret) { 3729a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "request interrupt failed.\n"); 373e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall goto fail; 3749a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3759a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->irq = res->start; 3769a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 3779a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* acquire clocks */ 3789a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->sclk_dac = clk_get(dev, "sclk_dac"); 379cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->sclk_dac)) { 3809a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get clock 'sclk_dac'\n"); 381cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->sclk_dac); 382e861dccc6d8d870d764ed950417cfb0e65889b90Julia Lawall goto fail; 3839a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3849a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->dac = clk_get(dev, "dac"); 385cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->dac)) { 3869a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get clock 'dac'\n"); 387cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->dac); 3889a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail_sclk_dac; 3899a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3909a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->dacphy = clk_get(dev, "dacphy"); 391cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->dacphy)) { 3929a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get clock 'dacphy'\n"); 393cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->dacphy); 3949a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail_dac; 3959a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 3969a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sclk_vpll = clk_get(dev, "sclk_vpll"); 397cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sclk_vpll)) { 3989a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get clock 'sclk_vpll'\n"); 399cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sclk_vpll); 4009a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail_dacphy; 4019a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 4029a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_set_parent(sdev->sclk_dac, sclk_vpll); 4039a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sclk_vpll); 4049a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->fout_vpll = clk_get(dev, "fout_vpll"); 405cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->fout_vpll)) { 4069a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get clock 'fout_vpll'\n"); 407cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->fout_vpll); 4089a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail_dacphy; 4099a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 4109a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "fout_vpll.rate = %lu\n", clk_get_rate(sclk_vpll)); 4119a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4129a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* acquire regulator */ 41300d98c1bd6fe93de6db6a99ed25b4b7d96a402ecSachin Kamat sdev->vdac = devm_regulator_get(dev, "vdd33a_dac"); 414cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->vdac)) { 4159a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get regulator 'vdac'\n"); 416cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->vdac); 4179a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski goto fail_fout_vpll; 4189a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 41900d98c1bd6fe93de6db6a99ed25b4b7d96a402ecSachin Kamat sdev->vdet = devm_regulator_get(dev, "vdet"); 420cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki if (IS_ERR(sdev->vdet)) { 4219a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_err(dev, "failed to get regulator 'vdet'\n"); 422cf48f56c27ecfe94fbea363db6e8e0bacbd525edSylwester Nawrocki ret = PTR_ERR(sdev->vdet); 42300d98c1bd6fe93de6db6a99ed25b4b7d96a402ecSachin Kamat goto fail_fout_vpll; 4249a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 4259a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4269a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* enable gate for dac clock, because mixer uses it */ 427a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk ret = clk_prepare_enable(sdev->dac); 428a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk if (ret < 0) { 429a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk dev_err(dev, "clk_prepare_enable(dac) failed\n"); 430a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk goto fail_fout_vpll; 431a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk } 4329a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4339a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* configure power management */ 4349a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski pm_runtime_enable(dev); 4359a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4369a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* configuration of interface subdevice */ 4379a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski v4l2_subdev_init(&sdev->sd, &sdo_sd_ops); 4389a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->sd.owner = THIS_MODULE; 43980f0dee21c7ec39f76f90548c9f08a0e7ec9b3faSachin Kamat strlcpy(sdev->sd.name, "s5p-sdo", sizeof(sdev->sd.name)); 4409a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4419a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* set default format */ 4429a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski sdev->fmt = sdo_find_format(SDO_DEFAULT_STD); 4439a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski BUG_ON(sdev->fmt == NULL); 4449a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4459a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski /* keeping subdev in device's private for use by other drivers */ 4469a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_set_drvdata(dev, &sdev->sd); 4479a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4489a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "probe succeeded\n"); 4499a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 4509a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4519a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskifail_fout_vpll: 4529a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->fout_vpll); 4539a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskifail_dacphy: 4549a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->dacphy); 4559a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskifail_dac: 4569a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->dac); 4579a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskifail_sclk_dac: 4589a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->sclk_dac); 4599a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskifail: 4609a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(dev, "probe failed\n"); 4619a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return ret; 4629a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 4639a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4644c62e9764ab403d42f9b8871b1241fe7812f19d4Greg Kroah-Hartmanstatic int sdo_remove(struct platform_device *pdev) 4659a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski{ 4669a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev); 4679a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski struct sdo_device *sdev = sd_to_sdev(sd); 4689a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4699a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski pm_runtime_disable(&pdev->dev); 470a889c11519b425dce284c6233cfb4629f519ccacMateusz Krawczuk clk_disable_unprepare(sdev->dac); 4719a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->fout_vpll); 4729a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->dacphy); 4739a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->dac); 4749a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski clk_put(sdev->sclk_dac); 4759a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4769a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski dev_info(&pdev->dev, "remove successful\n"); 4779a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski return 0; 4789a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski} 4799a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4809a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawskistatic struct platform_driver sdo_driver __refdata = { 4819a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .probe = sdo_probe, 4824c62e9764ab403d42f9b8871b1241fe7812f19d4Greg Kroah-Hartman .remove = sdo_remove, 4839a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .driver = { 4849a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .name = "s5p-sdo", 4859a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .owner = THIS_MODULE, 4869a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski .pm = &sdo_pm_ops, 4879a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski } 4889a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski}; 4899a498400fede652a5ada51e74ae47bba99c7ed07Tomasz Stanislawski 4901d6629b1561ad34a6e6d17ece00bd65e1bab3724Axel Linmodule_platform_driver(sdo_driver); 491