linux/drivers/media/platform/exynos4-is/mipi-csis.c
<<
>>
Prefs
   1/*
   2 * Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver
   3 *
   4 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
   5 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/clk.h>
  13#include <linux/delay.h>
  14#include <linux/device.h>
  15#include <linux/errno.h>
  16#include <linux/interrupt.h>
  17#include <linux/io.h>
  18#include <linux/irq.h>
  19#include <linux/kernel.h>
  20#include <linux/memory.h>
  21#include <linux/module.h>
  22#include <linux/of.h>
  23#include <linux/of_graph.h>
  24#include <linux/phy/phy.h>
  25#include <linux/platform_data/mipi-csis.h>
  26#include <linux/platform_device.h>
  27#include <linux/pm_runtime.h>
  28#include <linux/regulator/consumer.h>
  29#include <linux/slab.h>
  30#include <linux/spinlock.h>
  31#include <linux/videodev2.h>
  32#include <media/s5p_fimc.h>
  33#include <media/v4l2-of.h>
  34#include <media/v4l2-subdev.h>
  35
  36#include "mipi-csis.h"
  37
  38static int debug;
  39module_param(debug, int, 0644);
  40MODULE_PARM_DESC(debug, "Debug level (0-2)");
  41
  42/* Register map definition */
  43
  44/* CSIS global control */
  45#define S5PCSIS_CTRL                    0x00
  46#define S5PCSIS_CTRL_DPDN_DEFAULT       (0 << 31)
  47#define S5PCSIS_CTRL_DPDN_SWAP          (1 << 31)
  48#define S5PCSIS_CTRL_ALIGN_32BIT        (1 << 20)
  49#define S5PCSIS_CTRL_UPDATE_SHADOW      (1 << 16)
  50#define S5PCSIS_CTRL_WCLK_EXTCLK        (1 << 8)
  51#define S5PCSIS_CTRL_RESET              (1 << 4)
  52#define S5PCSIS_CTRL_ENABLE             (1 << 0)
  53
  54/* D-PHY control */
  55#define S5PCSIS_DPHYCTRL                0x04
  56#define S5PCSIS_DPHYCTRL_HSS_MASK       (0x1f << 27)
  57#define S5PCSIS_DPHYCTRL_ENABLE         (0x1f << 0)
  58
  59#define S5PCSIS_CONFIG                  0x08
  60#define S5PCSIS_CFG_FMT_YCBCR422_8BIT   (0x1e << 2)
  61#define S5PCSIS_CFG_FMT_RAW8            (0x2a << 2)
  62#define S5PCSIS_CFG_FMT_RAW10           (0x2b << 2)
  63#define S5PCSIS_CFG_FMT_RAW12           (0x2c << 2)
  64/* User defined formats, x = 1...4 */
  65#define S5PCSIS_CFG_FMT_USER(x)         ((0x30 + x - 1) << 2)
  66#define S5PCSIS_CFG_FMT_MASK            (0x3f << 2)
  67#define S5PCSIS_CFG_NR_LANE_MASK        3
  68
  69/* Interrupt mask */
  70#define S5PCSIS_INTMSK                  0x10
  71#define S5PCSIS_INTMSK_EVEN_BEFORE      (1 << 31)
  72#define S5PCSIS_INTMSK_EVEN_AFTER       (1 << 30)
  73#define S5PCSIS_INTMSK_ODD_BEFORE       (1 << 29)
  74#define S5PCSIS_INTMSK_ODD_AFTER        (1 << 28)
  75#define S5PCSIS_INTMSK_FRAME_START      (1 << 27)
  76#define S5PCSIS_INTMSK_FRAME_END        (1 << 26)
  77#define S5PCSIS_INTMSK_ERR_SOT_HS       (1 << 12)
  78#define S5PCSIS_INTMSK_ERR_LOST_FS      (1 << 5)
  79#define S5PCSIS_INTMSK_ERR_LOST_FE      (1 << 4)
  80#define S5PCSIS_INTMSK_ERR_OVER         (1 << 3)
  81#define S5PCSIS_INTMSK_ERR_ECC          (1 << 2)
  82#define S5PCSIS_INTMSK_ERR_CRC          (1 << 1)
  83#define S5PCSIS_INTMSK_ERR_UNKNOWN      (1 << 0)
  84#define S5PCSIS_INTMSK_EXYNOS4_EN_ALL   0xf000103f
  85#define S5PCSIS_INTMSK_EXYNOS5_EN_ALL   0xfc00103f
  86
  87/* Interrupt source */
  88#define S5PCSIS_INTSRC                  0x14
  89#define S5PCSIS_INTSRC_EVEN_BEFORE      (1 << 31)
  90#define S5PCSIS_INTSRC_EVEN_AFTER       (1 << 30)
  91#define S5PCSIS_INTSRC_EVEN             (0x3 << 30)
  92#define S5PCSIS_INTSRC_ODD_BEFORE       (1 << 29)
  93#define S5PCSIS_INTSRC_ODD_AFTER        (1 << 28)
  94#define S5PCSIS_INTSRC_ODD              (0x3 << 28)
  95#define S5PCSIS_INTSRC_NON_IMAGE_DATA   (0xf << 28)
  96#define S5PCSIS_INTSRC_FRAME_START      (1 << 27)
  97#define S5PCSIS_INTSRC_FRAME_END        (1 << 26)
  98#define S5PCSIS_INTSRC_ERR_SOT_HS       (0xf << 12)
  99#define S5PCSIS_INTSRC_ERR_LOST_FS      (1 << 5)
 100#define S5PCSIS_INTSRC_ERR_LOST_FE      (1 << 4)
 101#define S5PCSIS_INTSRC_ERR_OVER         (1 << 3)
 102#define S5PCSIS_INTSRC_ERR_ECC          (1 << 2)
 103#define S5PCSIS_INTSRC_ERR_CRC          (1 << 1)
 104#define S5PCSIS_INTSRC_ERR_UNKNOWN      (1 << 0)
 105#define S5PCSIS_INTSRC_ERRORS           0xf03f
 106
 107/* Pixel resolution */
 108#define S5PCSIS_RESOL                   0x2c
 109#define CSIS_MAX_PIX_WIDTH              0xffff
 110#define CSIS_MAX_PIX_HEIGHT             0xffff
 111
 112/* Non-image packet data buffers */
 113#define S5PCSIS_PKTDATA_ODD             0x2000
 114#define S5PCSIS_PKTDATA_EVEN            0x3000
 115#define S5PCSIS_PKTDATA_SIZE            SZ_4K
 116
 117enum {
 118        CSIS_CLK_MUX,
 119        CSIS_CLK_GATE,
 120};
 121
 122static char *csi_clock_name[] = {
 123        [CSIS_CLK_MUX]  = "sclk_csis",
 124        [CSIS_CLK_GATE] = "csis",
 125};
 126#define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
 127#define DEFAULT_SCLK_CSIS_FREQ  166000000UL
 128
 129static const char * const csis_supply_name[] = {
 130        "vddcore",  /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
 131        "vddio",    /* CSIS I/O and PLL (1.8V) supply */
 132};
 133#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
 134
 135enum {
 136        ST_POWERED      = 1,
 137        ST_STREAMING    = 2,
 138        ST_SUSPENDED    = 4,
 139};
 140
 141struct s5pcsis_event {
 142        u32 mask;
 143        const char * const name;
 144        unsigned int counter;
 145};
 146
 147static const struct s5pcsis_event s5pcsis_events[] = {
 148        /* Errors */
 149        { S5PCSIS_INTSRC_ERR_SOT_HS,    "SOT Error" },
 150        { S5PCSIS_INTSRC_ERR_LOST_FS,   "Lost Frame Start Error" },
 151        { S5PCSIS_INTSRC_ERR_LOST_FE,   "Lost Frame End Error" },
 152        { S5PCSIS_INTSRC_ERR_OVER,      "FIFO Overflow Error" },
 153        { S5PCSIS_INTSRC_ERR_ECC,       "ECC Error" },
 154        { S5PCSIS_INTSRC_ERR_CRC,       "CRC Error" },
 155        { S5PCSIS_INTSRC_ERR_UNKNOWN,   "Unknown Error" },
 156        /* Non-image data receive events */
 157        { S5PCSIS_INTSRC_EVEN_BEFORE,   "Non-image data before even frame" },
 158        { S5PCSIS_INTSRC_EVEN_AFTER,    "Non-image data after even frame" },
 159        { S5PCSIS_INTSRC_ODD_BEFORE,    "Non-image data before odd frame" },
 160        { S5PCSIS_INTSRC_ODD_AFTER,     "Non-image data after odd frame" },
 161        /* Frame start/end */
 162        { S5PCSIS_INTSRC_FRAME_START,   "Frame Start" },
 163        { S5PCSIS_INTSRC_FRAME_END,     "Frame End" },
 164};
 165#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
 166
 167struct csis_pktbuf {
 168        u32 *data;
 169        unsigned int len;
 170};
 171
 172struct csis_drvdata {
 173        /* Mask of all used interrupts in S5PCSIS_INTMSK register */
 174        u32 interrupt_mask;
 175};
 176
 177/**
 178 * struct csis_state - the driver's internal state data structure
 179 * @lock: mutex serializing the subdev and power management operations,
 180 *        protecting @format and @flags members
 181 * @pads: CSIS pads array
 182 * @sd: v4l2_subdev associated with CSIS device instance
 183 * @index: the hardware instance index
 184 * @pdev: CSIS platform device
 185 * @phy: pointer to the CSIS generic PHY
 186 * @regs: mmaped I/O registers memory
 187 * @supplies: CSIS regulator supplies
 188 * @clock: CSIS clocks
 189 * @irq: requested s5p-mipi-csis irq number
 190 * @interrupt_mask: interrupt mask of the all used interrupts
 191 * @flags: the state variable for power and streaming control
 192 * @clock_frequency: device bus clock frequency
 193 * @hs_settle: HS-RX settle time
 194 * @num_lanes: number of MIPI-CSI data lanes used
 195 * @max_num_lanes: maximum number of MIPI-CSI data lanes supported
 196 * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM
 197 * @csis_fmt: current CSIS pixel format
 198 * @format: common media bus format for the source and sink pad
 199 * @slock: spinlock protecting structure members below
 200 * @pkt_buf: the frame embedded (non-image) data buffer
 201 * @events: MIPI-CSIS event (error) counters
 202 */
 203struct csis_state {
 204        struct mutex lock;
 205        struct media_pad pads[CSIS_PADS_NUM];
 206        struct v4l2_subdev sd;
 207        u8 index;
 208        struct platform_device *pdev;
 209        struct phy *phy;
 210        void __iomem *regs;
 211        struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
 212        struct clk *clock[NUM_CSIS_CLOCKS];
 213        int irq;
 214        u32 interrupt_mask;
 215        u32 flags;
 216
 217        u32 clk_frequency;
 218        u32 hs_settle;
 219        u32 num_lanes;
 220        u32 max_num_lanes;
 221        u8 wclk_ext;
 222
 223        const struct csis_pix_format *csis_fmt;
 224        struct v4l2_mbus_framefmt format;
 225
 226        spinlock_t slock;
 227        struct csis_pktbuf pkt_buf;
 228        struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
 229};
 230
 231/**
 232 * struct csis_pix_format - CSIS pixel format description
 233 * @pix_width_alignment: horizontal pixel alignment, width will be
 234 *                       multiple of 2^pix_width_alignment
 235 * @code: corresponding media bus code
 236 * @fmt_reg: S5PCSIS_CONFIG register value
 237 * @data_alignment: MIPI-CSI data alignment in bits
 238 */
 239struct csis_pix_format {
 240        unsigned int pix_width_alignment;
 241        enum v4l2_mbus_pixelcode code;
 242        u32 fmt_reg;
 243        u8 data_alignment;
 244};
 245
 246static const struct csis_pix_format s5pcsis_formats[] = {
 247        {
 248                .code = V4L2_MBUS_FMT_VYUY8_2X8,
 249                .fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT,
 250                .data_alignment = 32,
 251        }, {
 252                .code = V4L2_MBUS_FMT_JPEG_1X8,
 253                .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
 254                .data_alignment = 32,
 255        }, {
 256                .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
 257                .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
 258                .data_alignment = 32,
 259        }, {
 260                .code = V4L2_MBUS_FMT_SGRBG8_1X8,
 261                .fmt_reg = S5PCSIS_CFG_FMT_RAW8,
 262                .data_alignment = 24,
 263        }, {
 264                .code = V4L2_MBUS_FMT_SGRBG10_1X10,
 265                .fmt_reg = S5PCSIS_CFG_FMT_RAW10,
 266                .data_alignment = 24,
 267        }, {
 268                .code = V4L2_MBUS_FMT_SGRBG12_1X12,
 269                .fmt_reg = S5PCSIS_CFG_FMT_RAW12,
 270                .data_alignment = 24,
 271        }
 272};
 273
 274#define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
 275#define s5pcsis_read(__csis, __r) readl(__csis->regs + __r)
 276
 277static struct csis_state *sd_to_csis_state(struct v4l2_subdev *sdev)
 278{
 279        return container_of(sdev, struct csis_state, sd);
 280}
 281
 282static const struct csis_pix_format *find_csis_format(
 283        struct v4l2_mbus_framefmt *mf)
 284{
 285        int i;
 286
 287        for (i = 0; i < ARRAY_SIZE(s5pcsis_formats); i++)
 288                if (mf->code == s5pcsis_formats[i].code)
 289                        return &s5pcsis_formats[i];
 290        return NULL;
 291}
 292
 293static void s5pcsis_enable_interrupts(struct csis_state *state, bool on)
 294{
 295        u32 val = s5pcsis_read(state, S5PCSIS_INTMSK);
 296        if (on)
 297                val |= state->interrupt_mask;
 298        else
 299                val &= ~state->interrupt_mask;
 300        s5pcsis_write(state, S5PCSIS_INTMSK, val);
 301}
 302
 303static void s5pcsis_reset(struct csis_state *state)
 304{
 305        u32 val = s5pcsis_read(state, S5PCSIS_CTRL);
 306
 307        s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_RESET);
 308        udelay(10);
 309}
 310
 311static void s5pcsis_system_enable(struct csis_state *state, int on)
 312{
 313        u32 val, mask;
 314
 315        val = s5pcsis_read(state, S5PCSIS_CTRL);
 316        if (on)
 317                val |= S5PCSIS_CTRL_ENABLE;
 318        else
 319                val &= ~S5PCSIS_CTRL_ENABLE;
 320        s5pcsis_write(state, S5PCSIS_CTRL, val);
 321
 322        val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
 323        val &= ~S5PCSIS_DPHYCTRL_ENABLE;
 324        if (on) {
 325                mask = (1 << (state->num_lanes + 1)) - 1;
 326                val |= (mask & S5PCSIS_DPHYCTRL_ENABLE);
 327        }
 328        s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
 329}
 330
 331/* Called with the state.lock mutex held */
 332static void __s5pcsis_set_format(struct csis_state *state)
 333{
 334        struct v4l2_mbus_framefmt *mf = &state->format;
 335        u32 val;
 336
 337        v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
 338                 mf->code, mf->width, mf->height);
 339
 340        /* Color format */
 341        val = s5pcsis_read(state, S5PCSIS_CONFIG);
 342        val = (val & ~S5PCSIS_CFG_FMT_MASK) | state->csis_fmt->fmt_reg;
 343        s5pcsis_write(state, S5PCSIS_CONFIG, val);
 344
 345        /* Pixel resolution */
 346        val = (mf->width << 16) | mf->height;
 347        s5pcsis_write(state, S5PCSIS_RESOL, val);
 348}
 349
 350static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle)
 351{
 352        u32 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
 353
 354        val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (settle << 27);
 355        s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
 356}
 357
 358static void s5pcsis_set_params(struct csis_state *state)
 359{
 360        u32 val;
 361
 362        val = s5pcsis_read(state, S5PCSIS_CONFIG);
 363        val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (state->num_lanes - 1);
 364        s5pcsis_write(state, S5PCSIS_CONFIG, val);
 365
 366        __s5pcsis_set_format(state);
 367        s5pcsis_set_hsync_settle(state, state->hs_settle);
 368
 369        val = s5pcsis_read(state, S5PCSIS_CTRL);
 370        if (state->csis_fmt->data_alignment == 32)
 371                val |= S5PCSIS_CTRL_ALIGN_32BIT;
 372        else /* 24-bits */
 373                val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
 374
 375        val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
 376        if (state->wclk_ext)
 377                val |= S5PCSIS_CTRL_WCLK_EXTCLK;
 378        s5pcsis_write(state, S5PCSIS_CTRL, val);
 379
 380        /* Update the shadow register. */
 381        val = s5pcsis_read(state, S5PCSIS_CTRL);
 382        s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_UPDATE_SHADOW);
 383}
 384
 385static void s5pcsis_clk_put(struct csis_state *state)
 386{
 387        int i;
 388
 389        for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
 390                if (IS_ERR(state->clock[i]))
 391                        continue;
 392                clk_unprepare(state->clock[i]);
 393                clk_put(state->clock[i]);
 394                state->clock[i] = ERR_PTR(-EINVAL);
 395        }
 396}
 397
 398static int s5pcsis_clk_get(struct csis_state *state)
 399{
 400        struct device *dev = &state->pdev->dev;
 401        int i, ret;
 402
 403        for (i = 0; i < NUM_CSIS_CLOCKS; i++)
 404                state->clock[i] = ERR_PTR(-EINVAL);
 405
 406        for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
 407                state->clock[i] = clk_get(dev, csi_clock_name[i]);
 408                if (IS_ERR(state->clock[i])) {
 409                        ret = PTR_ERR(state->clock[i]);
 410                        goto err;
 411                }
 412                ret = clk_prepare(state->clock[i]);
 413                if (ret < 0) {
 414                        clk_put(state->clock[i]);
 415                        state->clock[i] = ERR_PTR(-EINVAL);
 416                        goto err;
 417                }
 418        }
 419        return 0;
 420err:
 421        s5pcsis_clk_put(state);
 422        dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]);
 423        return ret;
 424}
 425
 426static void dump_regs(struct csis_state *state, const char *label)
 427{
 428        struct {
 429                u32 offset;
 430                const char * const name;
 431        } registers[] = {
 432                { 0x00, "CTRL" },
 433                { 0x04, "DPHYCTRL" },
 434                { 0x08, "CONFIG" },
 435                { 0x0c, "DPHYSTS" },
 436                { 0x10, "INTMSK" },
 437                { 0x2c, "RESOL" },
 438                { 0x38, "SDW_CONFIG" },
 439        };
 440        u32 i;
 441
 442        v4l2_info(&state->sd, "--- %s ---\n", label);
 443
 444        for (i = 0; i < ARRAY_SIZE(registers); i++) {
 445                u32 cfg = s5pcsis_read(state, registers[i].offset);
 446                v4l2_info(&state->sd, "%10s: 0x%08x\n", registers[i].name, cfg);
 447        }
 448}
 449
 450static void s5pcsis_start_stream(struct csis_state *state)
 451{
 452        s5pcsis_reset(state);
 453        s5pcsis_set_params(state);
 454        s5pcsis_system_enable(state, true);
 455        s5pcsis_enable_interrupts(state, true);
 456}
 457
 458static void s5pcsis_stop_stream(struct csis_state *state)
 459{
 460        s5pcsis_enable_interrupts(state, false);
 461        s5pcsis_system_enable(state, false);
 462}
 463
 464static void s5pcsis_clear_counters(struct csis_state *state)
 465{
 466        unsigned long flags;
 467        int i;
 468
 469        spin_lock_irqsave(&state->slock, flags);
 470        for (i = 0; i < S5PCSIS_NUM_EVENTS; i++)
 471                state->events[i].counter = 0;
 472        spin_unlock_irqrestore(&state->slock, flags);
 473}
 474
 475static void s5pcsis_log_counters(struct csis_state *state, bool non_errors)
 476{
 477        int i = non_errors ? S5PCSIS_NUM_EVENTS : S5PCSIS_NUM_EVENTS - 4;
 478        unsigned long flags;
 479
 480        spin_lock_irqsave(&state->slock, flags);
 481
 482        for (i--; i >= 0; i--) {
 483                if (state->events[i].counter > 0 || debug)
 484                        v4l2_info(&state->sd, "%s events: %d\n",
 485                                  state->events[i].name,
 486                                  state->events[i].counter);
 487        }
 488        spin_unlock_irqrestore(&state->slock, flags);
 489}
 490
 491/*
 492 * V4L2 subdev operations
 493 */
 494static int s5pcsis_s_power(struct v4l2_subdev *sd, int on)
 495{
 496        struct csis_state *state = sd_to_csis_state(sd);
 497        struct device *dev = &state->pdev->dev;
 498
 499        if (on)
 500                return pm_runtime_get_sync(dev);
 501
 502        return pm_runtime_put_sync(dev);
 503}
 504
 505static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
 506{
 507        struct csis_state *state = sd_to_csis_state(sd);
 508        int ret = 0;
 509
 510        v4l2_dbg(1, debug, sd, "%s: %d, state: 0x%x\n",
 511                 __func__, enable, state->flags);
 512
 513        if (enable) {
 514                s5pcsis_clear_counters(state);
 515                ret = pm_runtime_get_sync(&state->pdev->dev);
 516                if (ret && ret != 1)
 517                        return ret;
 518        }
 519
 520        mutex_lock(&state->lock);
 521        if (enable) {
 522                if (state->flags & ST_SUSPENDED) {
 523                        ret = -EBUSY;
 524                        goto unlock;
 525                }
 526                s5pcsis_start_stream(state);
 527                state->flags |= ST_STREAMING;
 528        } else {
 529                s5pcsis_stop_stream(state);
 530                state->flags &= ~ST_STREAMING;
 531                if (debug > 0)
 532                        s5pcsis_log_counters(state, true);
 533        }
 534unlock:
 535        mutex_unlock(&state->lock);
 536        if (!enable)
 537                pm_runtime_put(&state->pdev->dev);
 538
 539        return ret == 1 ? 0 : ret;
 540}
 541
 542static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd,
 543                                  struct v4l2_subdev_fh *fh,
 544                                  struct v4l2_subdev_mbus_code_enum *code)
 545{
 546        if (code->index >= ARRAY_SIZE(s5pcsis_formats))
 547                return -EINVAL;
 548
 549        code->code = s5pcsis_formats[code->index].code;
 550        return 0;
 551}
 552
 553static struct csis_pix_format const *s5pcsis_try_format(
 554        struct v4l2_mbus_framefmt *mf)
 555{
 556        struct csis_pix_format const *csis_fmt;
 557
 558        csis_fmt = find_csis_format(mf);
 559        if (csis_fmt == NULL)
 560                csis_fmt = &s5pcsis_formats[0];
 561
 562        mf->code = csis_fmt->code;
 563        v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
 564                              csis_fmt->pix_width_alignment,
 565                              &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
 566                              0);
 567        return csis_fmt;
 568}
 569
 570static struct v4l2_mbus_framefmt *__s5pcsis_get_format(
 571                struct csis_state *state, struct v4l2_subdev_fh *fh,
 572                enum v4l2_subdev_format_whence which)
 573{
 574        if (which == V4L2_SUBDEV_FORMAT_TRY)
 575                return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL;
 576
 577        return &state->format;
 578}
 579
 580static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 581                           struct v4l2_subdev_format *fmt)
 582{
 583        struct csis_state *state = sd_to_csis_state(sd);
 584        struct csis_pix_format const *csis_fmt;
 585        struct v4l2_mbus_framefmt *mf;
 586
 587        mf = __s5pcsis_get_format(state, fh, fmt->which);
 588
 589        if (fmt->pad == CSIS_PAD_SOURCE) {
 590                if (mf) {
 591                        mutex_lock(&state->lock);
 592                        fmt->format = *mf;
 593                        mutex_unlock(&state->lock);
 594                }
 595                return 0;
 596        }
 597        csis_fmt = s5pcsis_try_format(&fmt->format);
 598        if (mf) {
 599                mutex_lock(&state->lock);
 600                *mf = fmt->format;
 601                if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
 602                        state->csis_fmt = csis_fmt;
 603                mutex_unlock(&state->lock);
 604        }
 605        return 0;
 606}
 607
 608static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 609                           struct v4l2_subdev_format *fmt)
 610{
 611        struct csis_state *state = sd_to_csis_state(sd);
 612        struct v4l2_mbus_framefmt *mf;
 613
 614        mf = __s5pcsis_get_format(state, fh, fmt->which);
 615        if (!mf)
 616                return -EINVAL;
 617
 618        mutex_lock(&state->lock);
 619        fmt->format = *mf;
 620        mutex_unlock(&state->lock);
 621        return 0;
 622}
 623
 624static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf,
 625                               unsigned int *size)
 626{
 627        struct csis_state *state = sd_to_csis_state(sd);
 628        unsigned long flags;
 629
 630        *size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE);
 631
 632        spin_lock_irqsave(&state->slock, flags);
 633        state->pkt_buf.data = buf;
 634        state->pkt_buf.len = *size;
 635        spin_unlock_irqrestore(&state->slock, flags);
 636
 637        return 0;
 638}
 639
 640static int s5pcsis_log_status(struct v4l2_subdev *sd)
 641{
 642        struct csis_state *state = sd_to_csis_state(sd);
 643
 644        mutex_lock(&state->lock);
 645        s5pcsis_log_counters(state, true);
 646        if (debug && (state->flags & ST_POWERED))
 647                dump_regs(state, __func__);
 648        mutex_unlock(&state->lock);
 649        return 0;
 650}
 651
 652static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 653{
 654        struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
 655
 656        format->colorspace = V4L2_COLORSPACE_JPEG;
 657        format->code = s5pcsis_formats[0].code;
 658        format->width = S5PCSIS_DEF_PIX_WIDTH;
 659        format->height = S5PCSIS_DEF_PIX_HEIGHT;
 660        format->field = V4L2_FIELD_NONE;
 661
 662        return 0;
 663}
 664
 665static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = {
 666        .open = s5pcsis_open,
 667};
 668
 669static struct v4l2_subdev_core_ops s5pcsis_core_ops = {
 670        .s_power = s5pcsis_s_power,
 671        .log_status = s5pcsis_log_status,
 672};
 673
 674static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
 675        .enum_mbus_code = s5pcsis_enum_mbus_code,
 676        .get_fmt = s5pcsis_get_fmt,
 677        .set_fmt = s5pcsis_set_fmt,
 678};
 679
 680static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
 681        .s_rx_buffer = s5pcsis_s_rx_buffer,
 682        .s_stream = s5pcsis_s_stream,
 683};
 684
 685static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
 686        .core = &s5pcsis_core_ops,
 687        .pad = &s5pcsis_pad_ops,
 688        .video = &s5pcsis_video_ops,
 689};
 690
 691static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
 692{
 693        struct csis_state *state = dev_id;
 694        struct csis_pktbuf *pktbuf = &state->pkt_buf;
 695        unsigned long flags;
 696        u32 status;
 697
 698        status = s5pcsis_read(state, S5PCSIS_INTSRC);
 699        spin_lock_irqsave(&state->slock, flags);
 700
 701        if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
 702                u32 offset;
 703
 704                if (status & S5PCSIS_INTSRC_EVEN)
 705                        offset = S5PCSIS_PKTDATA_EVEN;
 706                else
 707                        offset = S5PCSIS_PKTDATA_ODD;
 708
 709                memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
 710                pktbuf->data = NULL;
 711                rmb();
 712        }
 713
 714        /* Update the event/error counters */
 715        if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
 716                int i;
 717                for (i = 0; i < S5PCSIS_NUM_EVENTS; i++) {
 718                        if (!(status & state->events[i].mask))
 719                                continue;
 720                        state->events[i].counter++;
 721                        v4l2_dbg(2, debug, &state->sd, "%s: %d\n",
 722                                 state->events[i].name,
 723                                 state->events[i].counter);
 724                }
 725                v4l2_dbg(2, debug, &state->sd, "status: %08x\n", status);
 726        }
 727        spin_unlock_irqrestore(&state->slock, flags);
 728
 729        s5pcsis_write(state, S5PCSIS_INTSRC, status);
 730        return IRQ_HANDLED;
 731}
 732
 733static int s5pcsis_get_platform_data(struct platform_device *pdev,
 734                                     struct csis_state *state)
 735{
 736        struct s5p_platform_mipi_csis *pdata = pdev->dev.platform_data;
 737
 738        if (pdata == NULL) {
 739                dev_err(&pdev->dev, "Platform data not specified\n");
 740                return -EINVAL;
 741        }
 742
 743        state->clk_frequency = pdata->clk_rate;
 744        state->num_lanes = pdata->lanes;
 745        state->hs_settle = pdata->hs_settle;
 746        state->index = max(0, pdev->id);
 747        state->max_num_lanes = state->index ? CSIS1_MAX_LANES :
 748                                              CSIS0_MAX_LANES;
 749        return 0;
 750}
 751
 752#ifdef CONFIG_OF
 753static int s5pcsis_parse_dt(struct platform_device *pdev,
 754                            struct csis_state *state)
 755{
 756        struct device_node *node = pdev->dev.of_node;
 757        struct v4l2_of_endpoint endpoint;
 758
 759        if (of_property_read_u32(node, "clock-frequency",
 760                                 &state->clk_frequency))
 761                state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
 762        if (of_property_read_u32(node, "bus-width",
 763                                 &state->max_num_lanes))
 764                return -EINVAL;
 765
 766        node = of_graph_get_next_endpoint(node, NULL);
 767        if (!node) {
 768                dev_err(&pdev->dev, "No port node at %s\n",
 769                                pdev->dev.of_node->full_name);
 770                return -EINVAL;
 771        }
 772        /* Get port node and validate MIPI-CSI channel id. */
 773        v4l2_of_parse_endpoint(node, &endpoint);
 774
 775        state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0;
 776        if (state->index < 0 || state->index >= CSIS_MAX_ENTITIES)
 777                return -ENXIO;
 778
 779        /* Get MIPI CSI-2 bus configration from the endpoint node. */
 780        of_property_read_u32(node, "samsung,csis-hs-settle",
 781                                        &state->hs_settle);
 782        state->wclk_ext = of_property_read_bool(node,
 783                                        "samsung,csis-wclk");
 784
 785        state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes;
 786        of_node_put(node);
 787
 788        return 0;
 789}
 790#else
 791#define s5pcsis_parse_dt(pdev, state) (-ENOSYS)
 792#endif
 793
 794static int s5pcsis_pm_resume(struct device *dev, bool runtime);
 795static const struct of_device_id s5pcsis_of_match[];
 796
 797static int s5pcsis_probe(struct platform_device *pdev)
 798{
 799        const struct of_device_id *of_id;
 800        const struct csis_drvdata *drv_data;
 801        struct device *dev = &pdev->dev;
 802        struct resource *mem_res;
 803        struct csis_state *state;
 804        int ret = -ENOMEM;
 805        int i;
 806
 807        state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
 808        if (!state)
 809                return -ENOMEM;
 810
 811        mutex_init(&state->lock);
 812        spin_lock_init(&state->slock);
 813        state->pdev = pdev;
 814
 815        if (dev->of_node) {
 816                of_id = of_match_node(s5pcsis_of_match, dev->of_node);
 817                if (WARN_ON(of_id == NULL))
 818                        return -EINVAL;
 819
 820                drv_data = of_id->data;
 821                state->interrupt_mask = drv_data->interrupt_mask;
 822
 823                ret = s5pcsis_parse_dt(pdev, state);
 824        } else {
 825                ret = s5pcsis_get_platform_data(pdev, state);
 826        }
 827
 828        if (ret < 0)
 829                return ret;
 830
 831        if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) {
 832                dev_err(dev, "Unsupported number of data lanes: %d (max. %d)\n",
 833                        state->num_lanes, state->max_num_lanes);
 834                return -EINVAL;
 835        }
 836
 837        state->phy = devm_phy_get(dev, "csis");
 838        if (IS_ERR(state->phy))
 839                return PTR_ERR(state->phy);
 840
 841        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 842        state->regs = devm_ioremap_resource(dev, mem_res);
 843        if (IS_ERR(state->regs))
 844                return PTR_ERR(state->regs);
 845
 846        state->irq = platform_get_irq(pdev, 0);
 847        if (state->irq < 0) {
 848                dev_err(dev, "Failed to get irq\n");
 849                return state->irq;
 850        }
 851
 852        for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
 853                state->supplies[i].supply = csis_supply_name[i];
 854
 855        ret = devm_regulator_bulk_get(dev, CSIS_NUM_SUPPLIES,
 856                                 state->supplies);
 857        if (ret)
 858                return ret;
 859
 860        ret = s5pcsis_clk_get(state);
 861        if (ret < 0)
 862                return ret;
 863
 864        if (state->clk_frequency)
 865                ret = clk_set_rate(state->clock[CSIS_CLK_MUX],
 866                                   state->clk_frequency);
 867        else
 868                dev_WARN(dev, "No clock frequency specified!\n");
 869        if (ret < 0)
 870                goto e_clkput;
 871
 872        ret = clk_enable(state->clock[CSIS_CLK_MUX]);
 873        if (ret < 0)
 874                goto e_clkput;
 875
 876        ret = devm_request_irq(dev, state->irq, s5pcsis_irq_handler,
 877                               0, dev_name(dev), state);
 878        if (ret) {
 879                dev_err(dev, "Interrupt request failed\n");
 880                goto e_clkdis;
 881        }
 882
 883        v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
 884        state->sd.owner = THIS_MODULE;
 885        snprintf(state->sd.name, sizeof(state->sd.name), "%s.%d",
 886                 CSIS_SUBDEV_NAME, state->index);
 887        state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 888        state->csis_fmt = &s5pcsis_formats[0];
 889
 890        state->format.code = s5pcsis_formats[0].code;
 891        state->format.width = S5PCSIS_DEF_PIX_WIDTH;
 892        state->format.height = S5PCSIS_DEF_PIX_HEIGHT;
 893
 894        state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
 895        state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
 896        ret = media_entity_init(&state->sd.entity,
 897                                CSIS_PADS_NUM, state->pads, 0);
 898        if (ret < 0)
 899                goto e_clkdis;
 900
 901        /* This allows to retrieve the platform device id by the host driver */
 902        v4l2_set_subdevdata(&state->sd, pdev);
 903
 904        /* .. and a pointer to the subdev. */
 905        platform_set_drvdata(pdev, &state->sd);
 906        memcpy(state->events, s5pcsis_events, sizeof(state->events));
 907
 908        pm_runtime_enable(dev);
 909        if (!pm_runtime_enabled(dev)) {
 910                ret = s5pcsis_pm_resume(dev, true);
 911                if (ret < 0)
 912                        goto e_m_ent;
 913        }
 914
 915        dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, wclk: %d, freq: %u\n",
 916                 state->num_lanes, state->hs_settle, state->wclk_ext,
 917                 state->clk_frequency);
 918        return 0;
 919
 920e_m_ent:
 921        media_entity_cleanup(&state->sd.entity);
 922e_clkdis:
 923        clk_disable(state->clock[CSIS_CLK_MUX]);
 924e_clkput:
 925        s5pcsis_clk_put(state);
 926        return ret;
 927}
 928
 929static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
 930{
 931        struct platform_device *pdev = to_platform_device(dev);
 932        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
 933        struct csis_state *state = sd_to_csis_state(sd);
 934        int ret = 0;
 935
 936        v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
 937                 __func__, state->flags);
 938
 939        mutex_lock(&state->lock);
 940        if (state->flags & ST_POWERED) {
 941                s5pcsis_stop_stream(state);
 942                ret = phy_power_off(state->phy);
 943                if (ret)
 944                        goto unlock;
 945                ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
 946                                             state->supplies);
 947                if (ret)
 948                        goto unlock;
 949                clk_disable(state->clock[CSIS_CLK_GATE]);
 950                state->flags &= ~ST_POWERED;
 951                if (!runtime)
 952                        state->flags |= ST_SUSPENDED;
 953        }
 954 unlock:
 955        mutex_unlock(&state->lock);
 956        return ret ? -EAGAIN : 0;
 957}
 958
 959static int s5pcsis_pm_resume(struct device *dev, bool runtime)
 960{
 961        struct platform_device *pdev = to_platform_device(dev);
 962        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
 963        struct csis_state *state = sd_to_csis_state(sd);
 964        int ret = 0;
 965
 966        v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
 967                 __func__, state->flags);
 968
 969        mutex_lock(&state->lock);
 970        if (!runtime && !(state->flags & ST_SUSPENDED))
 971                goto unlock;
 972
 973        if (!(state->flags & ST_POWERED)) {
 974                ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES,
 975                                            state->supplies);
 976                if (ret)
 977                        goto unlock;
 978                ret = phy_power_on(state->phy);
 979                if (!ret) {
 980                        state->flags |= ST_POWERED;
 981                } else {
 982                        regulator_bulk_disable(CSIS_NUM_SUPPLIES,
 983                                               state->supplies);
 984                        goto unlock;
 985                }
 986                clk_enable(state->clock[CSIS_CLK_GATE]);
 987        }
 988        if (state->flags & ST_STREAMING)
 989                s5pcsis_start_stream(state);
 990
 991        state->flags &= ~ST_SUSPENDED;
 992 unlock:
 993        mutex_unlock(&state->lock);
 994        return ret ? -EAGAIN : 0;
 995}
 996
 997#ifdef CONFIG_PM_SLEEP
 998static int s5pcsis_suspend(struct device *dev)
 999{
1000        return s5pcsis_pm_suspend(dev, false);
1001}
1002
1003static int s5pcsis_resume(struct device *dev)
1004{
1005        return s5pcsis_pm_resume(dev, false);
1006}
1007#endif
1008
1009#ifdef CONFIG_PM_RUNTIME
1010static int s5pcsis_runtime_suspend(struct device *dev)
1011{
1012        return s5pcsis_pm_suspend(dev, true);
1013}
1014
1015static int s5pcsis_runtime_resume(struct device *dev)
1016{
1017        return s5pcsis_pm_resume(dev, true);
1018}
1019#endif
1020
1021static int s5pcsis_remove(struct platform_device *pdev)
1022{
1023        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
1024        struct csis_state *state = sd_to_csis_state(sd);
1025
1026        pm_runtime_disable(&pdev->dev);
1027        s5pcsis_pm_suspend(&pdev->dev, true);
1028        clk_disable(state->clock[CSIS_CLK_MUX]);
1029        pm_runtime_set_suspended(&pdev->dev);
1030        s5pcsis_clk_put(state);
1031
1032        media_entity_cleanup(&state->sd.entity);
1033
1034        return 0;
1035}
1036
1037static const struct dev_pm_ops s5pcsis_pm_ops = {
1038        SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume,
1039                           NULL)
1040        SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
1041};
1042
1043static const struct csis_drvdata exynos4_csis_drvdata = {
1044        .interrupt_mask = S5PCSIS_INTMSK_EXYNOS4_EN_ALL,
1045};
1046
1047static const struct csis_drvdata exynos5_csis_drvdata = {
1048        .interrupt_mask = S5PCSIS_INTMSK_EXYNOS5_EN_ALL,
1049};
1050
1051static const struct of_device_id s5pcsis_of_match[] = {
1052        {
1053                .compatible = "samsung,s5pv210-csis",
1054                .data = &exynos4_csis_drvdata,
1055        }, {
1056                .compatible = "samsung,exynos4210-csis",
1057                .data = &exynos4_csis_drvdata,
1058        }, {
1059                .compatible = "samsung,exynos5250-csis",
1060                .data = &exynos5_csis_drvdata,
1061        },
1062        { /* sentinel */ },
1063};
1064MODULE_DEVICE_TABLE(of, s5pcsis_of_match);
1065
1066static struct platform_driver s5pcsis_driver = {
1067        .probe          = s5pcsis_probe,
1068        .remove         = s5pcsis_remove,
1069        .driver         = {
1070                .of_match_table = s5pcsis_of_match,
1071                .name           = CSIS_DRIVER_NAME,
1072                .owner          = THIS_MODULE,
1073                .pm             = &s5pcsis_pm_ops,
1074        },
1075};
1076
1077module_platform_driver(s5pcsis_driver);
1078
1079MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
1080MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver");
1081MODULE_LICENSE("GPL");
1082