linux/drivers/staging/dream/camera/msm_io8x.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2008-2009 QUALCOMM Incorporated
   3 */
   4
   5#include <linux/delay.h>
   6#include <linux/clk.h>
   7#include <linux/io.h>
   8#include <mach/gpio.h>
   9#include <mach/board.h>
  10#include <mach/camera.h>
  11
  12#define CAMIF_CFG_RMSK 0x1fffff
  13#define CAM_SEL_BMSK 0x2
  14#define CAM_PCLK_SRC_SEL_BMSK 0x60000
  15#define CAM_PCLK_INVERT_BMSK 0x80000
  16#define CAM_PAD_REG_SW_RESET_BMSK 0x100000
  17
  18#define EXT_CAM_HSYNC_POL_SEL_BMSK 0x10000
  19#define EXT_CAM_VSYNC_POL_SEL_BMSK 0x8000
  20#define MDDI_CLK_CHICKEN_BIT_BMSK  0x80
  21
  22#define CAM_SEL_SHFT 0x1
  23#define CAM_PCLK_SRC_SEL_SHFT 0x11
  24#define CAM_PCLK_INVERT_SHFT 0x13
  25#define CAM_PAD_REG_SW_RESET_SHFT 0x14
  26
  27#define EXT_CAM_HSYNC_POL_SEL_SHFT 0x10
  28#define EXT_CAM_VSYNC_POL_SEL_SHFT 0xF
  29#define MDDI_CLK_CHICKEN_BIT_SHFT  0x7
  30#define APPS_RESET_OFFSET 0x00000210
  31
  32static struct clk *camio_vfe_mdc_clk;
  33static struct clk *camio_mdc_clk;
  34static struct clk *camio_vfe_clk;
  35static struct clk *camio_vfe_axi_clk;
  36static struct msm_camera_io_ext camio_ext;
  37static struct resource *appio, *mdcio;
  38void __iomem *appbase, *mdcbase;
  39
  40extern int clk_set_flags(struct clk *clk, unsigned long flags);
  41
  42int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
  43{
  44        int rc = 0;
  45        struct clk *clk = NULL;
  46
  47        switch (clktype) {
  48        case CAMIO_VFE_MDC_CLK:
  49                camio_vfe_mdc_clk =
  50                clk = clk_get(NULL, "vfe_mdc_clk");
  51                break;
  52
  53        case CAMIO_MDC_CLK:
  54                camio_mdc_clk =
  55                clk = clk_get(NULL, "mdc_clk");
  56                break;
  57
  58        case CAMIO_VFE_CLK:
  59                camio_vfe_clk =
  60                clk = clk_get(NULL, "vfe_clk");
  61                break;
  62
  63        case CAMIO_VFE_AXI_CLK:
  64                camio_vfe_axi_clk =
  65                clk = clk_get(NULL, "vfe_axi_clk");
  66                break;
  67
  68        default:
  69                break;
  70        }
  71
  72        if (!IS_ERR(clk))
  73                clk_enable(clk);
  74        else
  75                rc = -1;
  76
  77        return rc;
  78}
  79
  80int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
  81{
  82        int rc = 0;
  83        struct clk *clk = NULL;
  84
  85        switch (clktype) {
  86        case CAMIO_VFE_MDC_CLK:
  87                clk = camio_vfe_mdc_clk;
  88                break;
  89
  90        case CAMIO_MDC_CLK:
  91                clk = camio_mdc_clk;
  92                break;
  93
  94        case CAMIO_VFE_CLK:
  95                clk = camio_vfe_clk;
  96                break;
  97
  98        case CAMIO_VFE_AXI_CLK:
  99                clk = camio_vfe_axi_clk;
 100                break;
 101
 102        default:
 103                break;
 104        }
 105
 106        if (!IS_ERR(clk)) {
 107                clk_disable(clk);
 108                clk_put(clk);
 109        } else
 110                rc = -1;
 111
 112        return rc;
 113}
 114
 115void msm_camio_clk_rate_set(int rate)
 116{
 117        struct clk *clk = camio_vfe_mdc_clk;
 118
 119        /* TODO: check return */
 120        clk_set_rate(clk, rate);
 121}
 122
 123int msm_camio_enable(struct platform_device *pdev)
 124{
 125        int rc = 0;
 126        struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
 127        struct msm_camera_device_platform_data *camdev = sinfo->pdata;
 128
 129        camio_ext = camdev->ioext;
 130
 131        appio = request_mem_region(camio_ext.appphy,
 132                camio_ext.appsz, pdev->name);
 133        if (!appio) {
 134                rc = -EBUSY;
 135                goto enable_fail;
 136        }
 137
 138        appbase = ioremap(camio_ext.appphy,
 139                camio_ext.appsz);
 140        if (!appbase) {
 141                rc = -ENOMEM;
 142                goto apps_no_mem;
 143        }
 144
 145        mdcio = request_mem_region(camio_ext.mdcphy,
 146                camio_ext.mdcsz, pdev->name);
 147        if (!mdcio) {
 148                rc = -EBUSY;
 149                goto mdc_busy;
 150        }
 151
 152        mdcbase = ioremap(camio_ext.mdcphy,
 153                camio_ext.mdcsz);
 154        if (!mdcbase) {
 155                rc = -ENOMEM;
 156                goto mdc_no_mem;
 157        }
 158
 159        camdev->camera_gpio_on();
 160
 161        msm_camio_clk_enable(CAMIO_VFE_CLK);
 162        msm_camio_clk_enable(CAMIO_MDC_CLK);
 163        msm_camio_clk_enable(CAMIO_VFE_MDC_CLK);
 164        msm_camio_clk_enable(CAMIO_VFE_AXI_CLK);
 165        return 0;
 166
 167mdc_no_mem:
 168        release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
 169mdc_busy:
 170        iounmap(appbase);
 171apps_no_mem:
 172        release_mem_region(camio_ext.appphy, camio_ext.appsz);
 173enable_fail:
 174        return rc;
 175}
 176
 177void msm_camio_disable(struct platform_device *pdev)
 178{
 179        struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
 180        struct msm_camera_device_platform_data *camdev = sinfo->pdata;
 181
 182        iounmap(mdcbase);
 183        release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
 184        iounmap(appbase);
 185        release_mem_region(camio_ext.appphy, camio_ext.appsz);
 186
 187        camdev->camera_gpio_off();
 188
 189        msm_camio_clk_disable(CAMIO_VFE_MDC_CLK);
 190        msm_camio_clk_disable(CAMIO_MDC_CLK);
 191        msm_camio_clk_disable(CAMIO_VFE_CLK);
 192        msm_camio_clk_disable(CAMIO_VFE_AXI_CLK);
 193}
 194
 195void msm_camio_camif_pad_reg_reset(void)
 196{
 197        uint32_t reg;
 198        uint32_t mask, value;
 199
 200        /* select CLKRGM_VFE_SRC_CAM_VFE_SRC:  internal source */
 201        msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_INTERNAL);
 202
 203        reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
 204
 205        mask = CAM_SEL_BMSK |
 206                CAM_PCLK_SRC_SEL_BMSK |
 207                CAM_PCLK_INVERT_BMSK |
 208                EXT_CAM_HSYNC_POL_SEL_BMSK |
 209                EXT_CAM_VSYNC_POL_SEL_BMSK |
 210                MDDI_CLK_CHICKEN_BIT_BMSK;
 211
 212        value = 1 << CAM_SEL_SHFT |
 213                3 << CAM_PCLK_SRC_SEL_SHFT |
 214                0 << CAM_PCLK_INVERT_SHFT |
 215                0 << EXT_CAM_HSYNC_POL_SEL_SHFT |
 216                0 << EXT_CAM_VSYNC_POL_SEL_SHFT |
 217                0 << MDDI_CLK_CHICKEN_BIT_SHFT;
 218        writel((reg & (~mask)) | (value & mask), mdcbase);
 219        mdelay(10);
 220
 221        reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
 222        mask = CAM_PAD_REG_SW_RESET_BMSK;
 223        value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
 224        writel((reg & (~mask)) | (value & mask), mdcbase);
 225        mdelay(10);
 226
 227        reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
 228        mask = CAM_PAD_REG_SW_RESET_BMSK;
 229        value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
 230        writel((reg & (~mask)) | (value & mask), mdcbase);
 231        mdelay(10);
 232
 233        msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_EXTERNAL);
 234
 235        mdelay(10);
 236
 237        /* todo: check return */
 238        if (camio_vfe_clk)
 239                clk_set_rate(camio_vfe_clk, 96000000);
 240}
 241
 242void msm_camio_vfe_blk_reset(void)
 243{
 244        uint32_t val;
 245
 246        val = readl(appbase + 0x00000210);
 247        val |= 0x1;
 248        writel(val, appbase + 0x00000210);
 249        mdelay(10);
 250
 251        val = readl(appbase + 0x00000210);
 252        val &= ~0x1;
 253        writel(val, appbase + 0x00000210);
 254        mdelay(10);
 255}
 256
 257void msm_camio_camif_pad_reg_reset_2(void)
 258{
 259        uint32_t reg;
 260        uint32_t mask, value;
 261
 262        reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
 263        mask = CAM_PAD_REG_SW_RESET_BMSK;
 264        value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
 265        writel((reg & (~mask)) | (value & mask), mdcbase);
 266        mdelay(10);
 267
 268        reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
 269        mask = CAM_PAD_REG_SW_RESET_BMSK;
 270        value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
 271        writel((reg & (~mask)) | (value & mask), mdcbase);
 272        mdelay(10);
 273}
 274
 275void msm_camio_clk_sel(enum msm_camio_clk_src_type srctype)
 276{
 277        struct clk *clk = NULL;
 278
 279        clk = camio_vfe_clk;
 280
 281        if (clk != NULL) {
 282                switch (srctype) {
 283                case MSM_CAMIO_CLK_SRC_INTERNAL:
 284                        clk_set_flags(clk, 0x00000100 << 1);
 285                        break;
 286
 287                case MSM_CAMIO_CLK_SRC_EXTERNAL:
 288                        clk_set_flags(clk, 0x00000100);
 289                        break;
 290
 291                default:
 292                        break;
 293                }
 294        }
 295}
 296
 297void msm_camio_clk_axi_rate_set(int rate)
 298{
 299        struct clk *clk = camio_vfe_axi_clk;
 300        /* todo: check return */
 301        clk_set_rate(clk, rate);
 302}
 303
 304int msm_camio_probe_on(struct platform_device *pdev)
 305{
 306        struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
 307        struct msm_camera_device_platform_data *camdev = sinfo->pdata;
 308
 309        camdev->camera_gpio_on();
 310        return msm_camio_clk_enable(CAMIO_VFE_MDC_CLK);
 311}
 312
 313int msm_camio_probe_off(struct platform_device *pdev)
 314{
 315        struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
 316        struct msm_camera_device_platform_data *camdev = sinfo->pdata;
 317
 318        camdev->camera_gpio_off();
 319        return msm_camio_clk_disable(CAMIO_VFE_MDC_CLK);
 320}
 321