media: atmel: atmel-isc: add his_entry to register offsets
[linux-2.6-microblaze.git] / drivers / media / platform / atmel / atmel-isc-base.c
index fe3ec8d..cfe60b2 100644 (file)
@@ -176,48 +176,6 @@ struct isc_format formats_list[] = {
 
 };
 
-/* Gamma table with gamma 1/2.2 */
-const u32 isc_gamma_table[GAMMA_MAX + 1][GAMMA_ENTRIES] = {
-       /* 0 --> gamma 1/1.8 */
-       {      0x65,  0x66002F,  0x950025,  0xBB0020,  0xDB001D,  0xF8001A,
-         0x1130018, 0x12B0017, 0x1420016, 0x1580014, 0x16D0013, 0x1810012,
-         0x1940012, 0x1A60012, 0x1B80011, 0x1C90010, 0x1DA0010, 0x1EA000F,
-         0x1FA000F, 0x209000F, 0x218000F, 0x227000E, 0x235000E, 0x243000E,
-         0x251000E, 0x25F000D, 0x26C000D, 0x279000D, 0x286000D, 0x293000C,
-         0x2A0000C, 0x2AC000C, 0x2B8000C, 0x2C4000C, 0x2D0000B, 0x2DC000B,
-         0x2E7000B, 0x2F3000B, 0x2FE000B, 0x309000B, 0x314000B, 0x31F000A,
-         0x32A000A, 0x334000B, 0x33F000A, 0x349000A, 0x354000A, 0x35E000A,
-         0x368000A, 0x372000A, 0x37C000A, 0x386000A, 0x3900009, 0x399000A,
-         0x3A30009, 0x3AD0009, 0x3B60009, 0x3BF000A, 0x3C90009, 0x3D20009,
-         0x3DB0009, 0x3E40009, 0x3ED0009, 0x3F60009 },
-
-       /* 1 --> gamma 1/2 */
-       {      0x7F,  0x800034,  0xB50028,  0xDE0021, 0x100001E, 0x11E001B,
-         0x1390019, 0x1520017, 0x16A0015, 0x1800014, 0x1940014, 0x1A80013,
-         0x1BB0012, 0x1CD0011, 0x1DF0010, 0x1EF0010, 0x200000F, 0x20F000F,
-         0x21F000E, 0x22D000F, 0x23C000E, 0x24A000E, 0x258000D, 0x265000D,
-         0x273000C, 0x27F000D, 0x28C000C, 0x299000C, 0x2A5000C, 0x2B1000B,
-         0x2BC000C, 0x2C8000B, 0x2D3000C, 0x2DF000B, 0x2EA000A, 0x2F5000A,
-         0x2FF000B, 0x30A000A, 0x314000B, 0x31F000A, 0x329000A, 0x333000A,
-         0x33D0009, 0x3470009, 0x350000A, 0x35A0009, 0x363000A, 0x36D0009,
-         0x3760009, 0x37F0009, 0x3880009, 0x3910009, 0x39A0009, 0x3A30009,
-         0x3AC0008, 0x3B40009, 0x3BD0008, 0x3C60008, 0x3CE0008, 0x3D60009,
-         0x3DF0008, 0x3E70008, 0x3EF0008, 0x3F70008 },
-
-       /* 2 --> gamma 1/2.2 */
-       {      0x99,  0x9B0038,  0xD4002A,  0xFF0023, 0x122001F, 0x141001B,
-         0x15D0019, 0x1760017, 0x18E0015, 0x1A30015, 0x1B80013, 0x1CC0012,
-         0x1DE0011, 0x1F00010, 0x2010010, 0x2110010, 0x221000F, 0x230000F,
-         0x23F000E, 0x24D000E, 0x25B000D, 0x269000C, 0x276000C, 0x283000C,
-         0x28F000C, 0x29B000C, 0x2A7000C, 0x2B3000B, 0x2BF000B, 0x2CA000B,
-         0x2D5000B, 0x2E0000A, 0x2EB000A, 0x2F5000A, 0x2FF000A, 0x30A000A,
-         0x3140009, 0x31E0009, 0x327000A, 0x3310009, 0x33A0009, 0x3440009,
-         0x34D0009, 0x3560009, 0x35F0009, 0x3680008, 0x3710008, 0x3790009,
-         0x3820008, 0x38A0008, 0x3930008, 0x39B0008, 0x3A30008, 0x3AB0008,
-         0x3B30008, 0x3BB0008, 0x3C30008, 0x3CB0007, 0x3D20008, 0x3DA0007,
-         0x3E20007, 0x3E90007, 0x3F00008, 0x3F80007 },
-};
-
 #define ISC_IS_FORMAT_RAW(mbus_code) \
        (((mbus_code) & 0xf000) == 0x3000)
 
@@ -294,9 +252,13 @@ static int isc_wait_clk_stable(struct clk_hw *hw)
 static int isc_clk_prepare(struct clk_hw *hw)
 {
        struct isc_clk *isc_clk = to_isc_clk(hw);
+       int ret;
 
-       if (isc_clk->id == ISC_ISPCK)
-               pm_runtime_get_sync(isc_clk->dev);
+       if (isc_clk->id == ISC_ISPCK) {
+               ret = pm_runtime_resume_and_get(isc_clk->dev);
+               if (ret < 0)
+                       return ret;
+       }
 
        return isc_wait_clk_stable(hw);
 }
@@ -319,8 +281,8 @@ static int isc_clk_enable(struct clk_hw *hw)
        unsigned long flags;
        unsigned int status;
 
-       dev_dbg(isc_clk->dev, "ISC CLK: %s, div = %d, parent id = %d\n",
-               __func__, isc_clk->div, isc_clk->parent_id);
+       dev_dbg(isc_clk->dev, "ISC CLK: %s, id = %d, div = %d, parent id = %d\n",
+               __func__, id, isc_clk->div, isc_clk->parent_id);
 
        spin_lock_irqsave(&isc_clk->lock, flags);
        regmap_update_bits(regmap, ISC_CLKCFG,
@@ -353,9 +315,13 @@ static int isc_clk_is_enabled(struct clk_hw *hw)
 {
        struct isc_clk *isc_clk = to_isc_clk(hw);
        u32 status;
+       int ret;
 
-       if (isc_clk->id == ISC_ISPCK)
-               pm_runtime_get_sync(isc_clk->dev);
+       if (isc_clk->id == ISC_ISPCK) {
+               ret = pm_runtime_resume_and_get(isc_clk->dev);
+               if (ret < 0)
+                       return 0;
+       }
 
        regmap_read(isc_clk->regmap, ISC_CLKSR, &status);
 
@@ -635,16 +601,20 @@ static void isc_start_dma(struct isc_device *isc)
                           ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN);
 
        addr0 = vb2_dma_contig_plane_dma_addr(&isc->cur_frm->vb.vb2_buf, 0);
-       regmap_write(regmap, ISC_DAD0, addr0);
+       regmap_write(regmap, ISC_DAD0 + isc->offsets.dma, addr0);
 
        switch (isc->config.fourcc) {
        case V4L2_PIX_FMT_YUV420:
-               regmap_write(regmap, ISC_DAD1, addr0 + (sizeimage * 2) / 3);
-               regmap_write(regmap, ISC_DAD2, addr0 + (sizeimage * 5) / 6);
+               regmap_write(regmap, ISC_DAD1 + isc->offsets.dma,
+                            addr0 + (sizeimage * 2) / 3);
+               regmap_write(regmap, ISC_DAD2 + isc->offsets.dma,
+                            addr0 + (sizeimage * 5) / 6);
                break;
        case V4L2_PIX_FMT_YUV422P:
-               regmap_write(regmap, ISC_DAD1, addr0 + sizeimage / 2);
-               regmap_write(regmap, ISC_DAD2, addr0 + (sizeimage * 3) / 4);
+               regmap_write(regmap, ISC_DAD1 + isc->offsets.dma,
+                            addr0 + sizeimage / 2);
+               regmap_write(regmap, ISC_DAD2 + isc->offsets.dma,
+                            addr0 + (sizeimage * 3) / 4);
                break;
        default:
                break;
@@ -652,7 +622,8 @@ static void isc_start_dma(struct isc_device *isc)
 
        dctrl_dview = isc->config.dctrl_dview;
 
-       regmap_write(regmap, ISC_DCTRL, dctrl_dview | ISC_DCTRL_IE_IS);
+       regmap_write(regmap, ISC_DCTRL + isc->offsets.dma,
+                    dctrl_dview | ISC_DCTRL_IE_IS);
        spin_lock(&isc->awb_lock);
        regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_CAPTURE);
        spin_unlock(&isc->awb_lock);
@@ -683,21 +654,13 @@ static void isc_set_pipeline(struct isc_device *isc, u32 pipeline)
 
        regmap_write(regmap, ISC_CFA_CFG, bay_cfg | ISC_CFA_CFG_EITPOL);
 
-       gamma = &isc_gamma_table[ctrls->gamma_index][0];
+       gamma = &isc->gamma_table[ctrls->gamma_index][0];
        regmap_bulk_write(regmap, ISC_GAM_BENTRY, gamma, GAMMA_ENTRIES);
        regmap_bulk_write(regmap, ISC_GAM_GENTRY, gamma, GAMMA_ENTRIES);
        regmap_bulk_write(regmap, ISC_GAM_RENTRY, gamma, GAMMA_ENTRIES);
 
-       /* Convert RGB to YUV */
-       regmap_write(regmap, ISC_CSC_YR_YG, 0x42 | (0x81 << 16));
-       regmap_write(regmap, ISC_CSC_YB_OY, 0x19 | (0x10 << 16));
-       regmap_write(regmap, ISC_CSC_CBR_CBG, 0xFDA | (0xFB6 << 16));
-       regmap_write(regmap, ISC_CSC_CBB_OCB, 0x70 | (0x80 << 16));
-       regmap_write(regmap, ISC_CSC_CRR_CRG, 0x70 | (0xFA2 << 16));
-       regmap_write(regmap, ISC_CSC_CRB_OCR, 0xFEE | (0x80 << 16));
-
-       regmap_write(regmap, ISC_CBC_BRIGHT, ctrls->brightness);
-       regmap_write(regmap, ISC_CBC_CONTRAST, ctrls->contrast);
+       isc->config_csc(isc);
+       isc->config_cbc(isc);
 }
 
 static int isc_update_profile(struct isc_device *isc)
@@ -728,12 +691,13 @@ static void isc_set_histogram(struct isc_device *isc, bool enable)
        struct isc_ctrls *ctrls = &isc->ctrls;
 
        if (enable) {
-               regmap_write(regmap, ISC_HIS_CFG,
+               regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his,
                             ISC_HIS_CFG_MODE_GR |
                             (isc->config.sd_format->cfa_baycfg
                                        << ISC_HIS_CFG_BAYSEL_SHIFT) |
                                        ISC_HIS_CFG_RAR);
-               regmap_write(regmap, ISC_HIS_CTRL, ISC_HIS_CTRL_EN);
+               regmap_write(regmap, ISC_HIS_CTRL + isc->offsets.his,
+                            ISC_HIS_CTRL_EN);
                regmap_write(regmap, ISC_INTEN, ISC_INT_HISDONE);
                ctrls->hist_id = ISC_HIS_CFG_MODE_GR;
                isc_update_profile(isc);
@@ -742,7 +706,8 @@ static void isc_set_histogram(struct isc_device *isc, bool enable)
                ctrls->hist_stat = HIST_ENABLED;
        } else {
                regmap_write(regmap, ISC_INTDIS, ISC_INT_HISDONE);
-               regmap_write(regmap, ISC_HIS_CTRL, ISC_HIS_CTRL_DIS);
+               regmap_write(regmap, ISC_HIS_CTRL + isc->offsets.his,
+                            ISC_HIS_CTRL_DIS);
 
                ctrls->hist_stat = HIST_DISABLED;
        }
@@ -758,8 +723,7 @@ static int isc_configure(struct isc_device *isc)
        rlp_mode = isc->config.rlp_cfg_mode;
        pipeline = isc->config.bits_pipeline;
 
-       dcfg = isc->config.dcfg_imode |
-                      ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8;
+       dcfg = isc->config.dcfg_imode | isc->dcfg;
 
        pfe_cfg0  |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE;
        mask = ISC_PFE_CFG0_BPS_MASK | ISC_PFE_CFG0_HPOL_LOW |
@@ -769,10 +733,10 @@ static int isc_configure(struct isc_device *isc)
 
        regmap_update_bits(regmap, ISC_PFE_CFG0, mask, pfe_cfg0);
 
-       regmap_update_bits(regmap, ISC_RLP_CFG, ISC_RLP_CFG_MODE_MASK,
-                          rlp_mode);
+       regmap_update_bits(regmap, ISC_RLP_CFG + isc->offsets.rlp,
+                          ISC_RLP_CFG_MODE_MASK, rlp_mode);
 
-       regmap_write(regmap, ISC_DCFG, dcfg);
+       regmap_write(regmap, ISC_DCFG + isc->offsets.dma, dcfg);
 
        /* Set the pipeline */
        isc_set_pipeline(isc, pipeline);
@@ -807,7 +771,12 @@ static int isc_start_streaming(struct vb2_queue *vq, unsigned int count)
                goto err_start_stream;
        }
 
-       pm_runtime_get_sync(isc->dev);
+       ret = pm_runtime_resume_and_get(isc->dev);
+       if (ret < 0) {
+               v4l2_err(&isc->v4l2_dev, "RPM resume failed in subdev %d\n",
+                        ret);
+               goto err_pm_get;
+       }
 
        ret = isc_configure(isc);
        if (unlikely(ret))
@@ -838,7 +807,7 @@ static int isc_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 err_configure:
        pm_runtime_put_sync(isc->dev);
-
+err_pm_get:
        v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0);
 
 err_start_stream:
@@ -938,7 +907,7 @@ static int isc_querycap(struct file *file, void *priv,
 {
        struct isc_device *isc = video_drvdata(file);
 
-       strscpy(cap->driver, ATMEL_ISC_NAME, sizeof(cap->driver));
+       strscpy(cap->driver, "microchip-isc", sizeof(cap->driver));
        strscpy(cap->card, "Atmel Image Sensor Controller", sizeof(cap->card));
        snprintf(cap->bus_info, sizeof(cap->bus_info),
                 "platform:%s", isc->v4l2_dev.name);
@@ -959,7 +928,6 @@ static int isc_enum_fmt_vid_cap(struct file *file, void *priv,
 
        index -= ARRAY_SIZE(controller_formats);
 
-       i = 0;
        supported_index = 0;
 
        for (i = 0; i < ARRAY_SIZE(formats_list); i++) {
@@ -1246,8 +1214,8 @@ static void isc_try_fse(struct isc_device *isc,
         * just use the maximum ISC can receive.
         */
        if (ret) {
-               pad_cfg->try_crop.width = ISC_MAX_SUPPORT_WIDTH;
-               pad_cfg->try_crop.height = ISC_MAX_SUPPORT_HEIGHT;
+               pad_cfg->try_crop.width = isc->max_width;
+               pad_cfg->try_crop.height = isc->max_height;
        } else {
                pad_cfg->try_crop.width = fse.max_width;
                pad_cfg->try_crop.height = fse.max_height;
@@ -1324,10 +1292,10 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f,
        isc->try_config.sd_format = sd_fmt;
 
        /* Limit to Atmel ISC hardware capabilities */
-       if (pixfmt->width > ISC_MAX_SUPPORT_WIDTH)
-               pixfmt->width = ISC_MAX_SUPPORT_WIDTH;
-       if (pixfmt->height > ISC_MAX_SUPPORT_HEIGHT)
-               pixfmt->height = ISC_MAX_SUPPORT_HEIGHT;
+       if (pixfmt->width > isc->max_width)
+               pixfmt->width = isc->max_width;
+       if (pixfmt->height > isc->max_height)
+               pixfmt->height = isc->max_height;
 
        /*
         * The mbus format is the one the subdev outputs.
@@ -1368,6 +1336,12 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f,
 
        v4l2_fill_pix_format(pixfmt, &format.format);
 
+       /* Limit to Atmel ISC hardware capabilities */
+       if (pixfmt->width > isc->max_width)
+               pixfmt->width = isc->max_width;
+       if (pixfmt->height > isc->max_height)
+               pixfmt->height = isc->max_height;
+
        pixfmt->field = V4L2_FIELD_NONE;
        pixfmt->bytesperline = (pixfmt->width * isc->try_config.bpp) >> 3;
        pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
@@ -1403,6 +1377,12 @@ static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f)
        if (ret < 0)
                return ret;
 
+       /* Limit to Atmel ISC hardware capabilities */
+       if (f->fmt.pix.width > isc->max_width)
+               f->fmt.pix.width = isc->max_width;
+       if (f->fmt.pix.height > isc->max_height)
+               f->fmt.pix.height = isc->max_height;
+
        isc->fmt = *f;
 
        if (isc->try_config.sd_format && isc->config.sd_format &&
@@ -1704,7 +1684,8 @@ static void isc_hist_count(struct isc_device *isc, u32 *min, u32 *max)
        *min = 0;
        *max = HIST_ENTRIES;
 
-       regmap_bulk_read(regmap, ISC_HIS_ENTRY, hist_entry, HIST_ENTRIES);
+       regmap_bulk_read(regmap, ISC_HIS_ENTRY + isc->offsets.his_entry,
+                        hist_entry, HIST_ENTRIES);
 
        *hist_count = 0;
        /*
@@ -1809,6 +1790,7 @@ static void isc_awb_work(struct work_struct *w)
        u32 baysel;
        unsigned long flags;
        u32 min, max;
+       int ret;
 
        /* streaming is not active anymore */
        if (isc->stop)
@@ -1831,7 +1813,9 @@ static void isc_awb_work(struct work_struct *w)
        ctrls->hist_id = hist_id;
        baysel = isc->config.sd_format->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT;
 
-       pm_runtime_get_sync(isc->dev);
+       ret = pm_runtime_resume_and_get(isc->dev);
+       if (ret < 0)
+               return;
 
        /*
         * only update if we have all the required histograms and controls
@@ -1860,7 +1844,8 @@ static void isc_awb_work(struct work_struct *w)
                        ctrls->awb = ISC_WB_NONE;
                }
        }
-       regmap_write(regmap, ISC_HIS_CFG, hist_id | baysel | ISC_HIS_CFG_RAR);
+       regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his,
+                    hist_id | baysel | ISC_HIS_CFG_RAR);
        isc_update_profile(isc);
        /* if awb has been disabled, we don't need to start another histogram */
        if (ctrls->awb)
@@ -2070,7 +2055,8 @@ static int isc_ctrl_init(struct isc_device *isc)
 
        v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -1024, 1023, 1, 0);
        v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2048, 2047, 1, 256);
-       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 2);
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAMMA, 0, isc->gamma_max, 1,
+                         isc->gamma_max);
        isc->awb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops,
                                          V4L2_CID_AUTO_WHITE_BALANCE,
                                          0, 1, 1, 1);
@@ -2287,7 +2273,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
        }
 
        /* Register video device */
-       strscpy(vdev->name, ATMEL_ISC_NAME, sizeof(vdev->name));
+       strscpy(vdev->name, "microchip-isc", sizeof(vdev->name));
        vdev->release           = video_device_release_empty;
        vdev->fops              = &isc_fops;
        vdev->ioctl_ops         = &isc_ioctl_ops;
@@ -2347,10 +2333,10 @@ int isc_pipeline_init(struct isc_device *isc)
                REG_FIELD(ISC_GAM_CTRL, 1, 1),
                REG_FIELD(ISC_GAM_CTRL, 2, 2),
                REG_FIELD(ISC_GAM_CTRL, 3, 3),
-               REG_FIELD(ISC_CSC_CTRL, 0, 0),
-               REG_FIELD(ISC_CBC_CTRL, 0, 0),
-               REG_FIELD(ISC_SUB422_CTRL, 0, 0),
-               REG_FIELD(ISC_SUB420_CTRL, 0, 0),
+               REG_FIELD(ISC_CSC_CTRL + isc->offsets.csc, 0, 0),
+               REG_FIELD(ISC_CBC_CTRL + isc->offsets.cbc, 0, 0),
+               REG_FIELD(ISC_SUB422_CTRL + isc->offsets.sub422, 0, 0),
+               REG_FIELD(ISC_SUB420_CTRL + isc->offsets.sub420, 0, 0),
        };
 
        for (i = 0; i < ISC_PIPE_LINE_NODE_NUM; i++) {