Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2015 Samsung Electronics Co.Ltd
0004  * Authors:
0005  *  Hyungwon Hwang <human.hwang@samsung.com>
0006  */
0007 
0008 #include <linux/clk.h>
0009 #include <linux/component.h>
0010 #include <linux/delay.h>
0011 #include <linux/mfd/syscon.h>
0012 #include <linux/module.h>
0013 #include <linux/mutex.h>
0014 #include <linux/of.h>
0015 #include <linux/of_address.h>
0016 #include <linux/of_graph.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/pm_runtime.h>
0019 #include <linux/regmap.h>
0020 
0021 #include <video/of_videomode.h>
0022 #include <video/videomode.h>
0023 
0024 #include <drm/drm_bridge.h>
0025 #include <drm/drm_encoder.h>
0026 #include <drm/drm_print.h>
0027 
0028 #include "exynos_drm_drv.h"
0029 #include "exynos_drm_crtc.h"
0030 
0031 /* Sysreg registers for MIC */
0032 #define DSD_CFG_MUX 0x1004
0033 #define MIC0_RGB_MUX    (1 << 0)
0034 #define MIC0_I80_MUX    (1 << 1)
0035 #define MIC0_ON_MUX (1 << 5)
0036 
0037 /* MIC registers */
0038 #define MIC_OP              0x0
0039 #define MIC_IP_VER          0x0004
0040 #define MIC_V_TIMING_0          0x0008
0041 #define MIC_V_TIMING_1          0x000C
0042 #define MIC_IMG_SIZE            0x0010
0043 #define MIC_INPUT_TIMING_0      0x0014
0044 #define MIC_INPUT_TIMING_1      0x0018
0045 #define MIC_2D_OUTPUT_TIMING_0      0x001C
0046 #define MIC_2D_OUTPUT_TIMING_1      0x0020
0047 #define MIC_2D_OUTPUT_TIMING_2      0x0024
0048 #define MIC_3D_OUTPUT_TIMING_0      0x0028
0049 #define MIC_3D_OUTPUT_TIMING_1      0x002C
0050 #define MIC_3D_OUTPUT_TIMING_2      0x0030
0051 #define MIC_CORE_PARA_0         0x0034
0052 #define MIC_CORE_PARA_1         0x0038
0053 #define MIC_CTC_CTRL            0x0040
0054 #define MIC_RD_DATA         0x0044
0055 
0056 #define MIC_UPD_REG         (1 << 31)
0057 #define MIC_ON_REG          (1 << 30)
0058 #define MIC_TD_ON_REG           (1 << 29)
0059 #define MIC_BS_CHG_OUT          (1 << 16)
0060 #define MIC_VIDEO_TYPE(x)       (((x) & 0xf) << 12)
0061 #define MIC_PSR_EN          (1 << 5)
0062 #define MIC_SW_RST          (1 << 4)
0063 #define MIC_ALL_RST         (1 << 3)
0064 #define MIC_CORE_VER_CONTROL        (1 << 2)
0065 #define MIC_MODE_SEL_COMMAND_MODE   (1 << 1)
0066 #define MIC_MODE_SEL_MASK       (1 << 1)
0067 #define MIC_CORE_EN         (1 << 0)
0068 
0069 #define MIC_V_PULSE_WIDTH(x)        (((x) & 0x3fff) << 16)
0070 #define MIC_V_PERIOD_LINE(x)        ((x) & 0x3fff)
0071 
0072 #define MIC_VBP_SIZE(x)         (((x) & 0x3fff) << 16)
0073 #define MIC_VFP_SIZE(x)         ((x) & 0x3fff)
0074 
0075 #define MIC_IMG_V_SIZE(x)       (((x) & 0x3fff) << 16)
0076 #define MIC_IMG_H_SIZE(x)       ((x) & 0x3fff)
0077 
0078 #define MIC_H_PULSE_WIDTH_IN(x)     (((x) & 0x3fff) << 16)
0079 #define MIC_H_PERIOD_PIXEL_IN(x)    ((x) & 0x3fff)
0080 
0081 #define MIC_HBP_SIZE_IN(x)      (((x) & 0x3fff) << 16)
0082 #define MIC_HFP_SIZE_IN(x)      ((x) & 0x3fff)
0083 
0084 #define MIC_H_PULSE_WIDTH_2D(x)     (((x) & 0x3fff) << 16)
0085 #define MIC_H_PERIOD_PIXEL_2D(x)    ((x) & 0x3fff)
0086 
0087 #define MIC_HBP_SIZE_2D(x)      (((x) & 0x3fff) << 16)
0088 #define MIC_HFP_SIZE_2D(x)      ((x) & 0x3fff)
0089 
0090 #define MIC_BS_SIZE_2D(x)   ((x) & 0x3fff)
0091 
0092 static const char *const clk_names[] = { "pclk_mic0", "sclk_rgb_vclk_to_mic0" };
0093 #define NUM_CLKS        ARRAY_SIZE(clk_names)
0094 static DEFINE_MUTEX(mic_mutex);
0095 
0096 struct exynos_mic {
0097     struct device *dev;
0098     void __iomem *reg;
0099     struct regmap *sysreg;
0100     struct clk *clks[NUM_CLKS];
0101 
0102     bool i80_mode;
0103     struct videomode vm;
0104     struct drm_bridge bridge;
0105 
0106     bool enabled;
0107 };
0108 
0109 static void mic_set_path(struct exynos_mic *mic, bool enable)
0110 {
0111     int ret;
0112     unsigned int val;
0113 
0114     ret = regmap_read(mic->sysreg, DSD_CFG_MUX, &val);
0115     if (ret) {
0116         DRM_DEV_ERROR(mic->dev,
0117                   "mic: Failed to read system register\n");
0118         return;
0119     }
0120 
0121     if (enable) {
0122         if (mic->i80_mode)
0123             val |= MIC0_I80_MUX;
0124         else
0125             val |= MIC0_RGB_MUX;
0126 
0127         val |=  MIC0_ON_MUX;
0128     } else
0129         val &= ~(MIC0_RGB_MUX | MIC0_I80_MUX | MIC0_ON_MUX);
0130 
0131     ret = regmap_write(mic->sysreg, DSD_CFG_MUX, val);
0132     if (ret)
0133         DRM_DEV_ERROR(mic->dev,
0134                   "mic: Failed to read system register\n");
0135 }
0136 
0137 static int mic_sw_reset(struct exynos_mic *mic)
0138 {
0139     unsigned int retry = 100;
0140     int ret;
0141 
0142     writel(MIC_SW_RST, mic->reg + MIC_OP);
0143 
0144     while (retry-- > 0) {
0145         ret = readl(mic->reg + MIC_OP);
0146         if (!(ret & MIC_SW_RST))
0147             return 0;
0148 
0149         udelay(10);
0150     }
0151 
0152     return -ETIMEDOUT;
0153 }
0154 
0155 static void mic_set_porch_timing(struct exynos_mic *mic)
0156 {
0157     struct videomode vm = mic->vm;
0158     u32 reg;
0159 
0160     reg = MIC_V_PULSE_WIDTH(vm.vsync_len) +
0161         MIC_V_PERIOD_LINE(vm.vsync_len + vm.vactive +
0162                 vm.vback_porch + vm.vfront_porch);
0163     writel(reg, mic->reg + MIC_V_TIMING_0);
0164 
0165     reg = MIC_VBP_SIZE(vm.vback_porch) +
0166         MIC_VFP_SIZE(vm.vfront_porch);
0167     writel(reg, mic->reg + MIC_V_TIMING_1);
0168 
0169     reg = MIC_V_PULSE_WIDTH(vm.hsync_len) +
0170         MIC_V_PERIOD_LINE(vm.hsync_len + vm.hactive +
0171                 vm.hback_porch + vm.hfront_porch);
0172     writel(reg, mic->reg + MIC_INPUT_TIMING_0);
0173 
0174     reg = MIC_VBP_SIZE(vm.hback_porch) +
0175         MIC_VFP_SIZE(vm.hfront_porch);
0176     writel(reg, mic->reg + MIC_INPUT_TIMING_1);
0177 }
0178 
0179 static void mic_set_img_size(struct exynos_mic *mic)
0180 {
0181     struct videomode *vm = &mic->vm;
0182     u32 reg;
0183 
0184     reg = MIC_IMG_H_SIZE(vm->hactive) +
0185         MIC_IMG_V_SIZE(vm->vactive);
0186 
0187     writel(reg, mic->reg + MIC_IMG_SIZE);
0188 }
0189 
0190 static void mic_set_output_timing(struct exynos_mic *mic)
0191 {
0192     struct videomode vm = mic->vm;
0193     u32 reg, bs_size_2d;
0194 
0195     DRM_DEV_DEBUG(mic->dev, "w: %u, h: %u\n", vm.hactive, vm.vactive);
0196     bs_size_2d = ((vm.hactive >> 2) << 1) + (vm.vactive % 4);
0197     reg = MIC_BS_SIZE_2D(bs_size_2d);
0198     writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_2);
0199 
0200     if (!mic->i80_mode) {
0201         reg = MIC_H_PULSE_WIDTH_2D(vm.hsync_len) +
0202             MIC_H_PERIOD_PIXEL_2D(vm.hsync_len + bs_size_2d +
0203                     vm.hback_porch + vm.hfront_porch);
0204         writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_0);
0205 
0206         reg = MIC_HBP_SIZE_2D(vm.hback_porch) +
0207             MIC_H_PERIOD_PIXEL_2D(vm.hfront_porch);
0208         writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_1);
0209     }
0210 }
0211 
0212 static void mic_set_reg_on(struct exynos_mic *mic, bool enable)
0213 {
0214     u32 reg = readl(mic->reg + MIC_OP);
0215 
0216     if (enable) {
0217         reg &= ~(MIC_MODE_SEL_MASK | MIC_CORE_VER_CONTROL | MIC_PSR_EN);
0218         reg |= (MIC_CORE_EN | MIC_BS_CHG_OUT | MIC_ON_REG);
0219 
0220         reg  &= ~MIC_MODE_SEL_COMMAND_MODE;
0221         if (mic->i80_mode)
0222             reg |= MIC_MODE_SEL_COMMAND_MODE;
0223     } else {
0224         reg &= ~MIC_CORE_EN;
0225     }
0226 
0227     reg |= MIC_UPD_REG;
0228     writel(reg, mic->reg + MIC_OP);
0229 }
0230 
0231 static void mic_post_disable(struct drm_bridge *bridge)
0232 {
0233     struct exynos_mic *mic = bridge->driver_private;
0234 
0235     mutex_lock(&mic_mutex);
0236     if (!mic->enabled)
0237         goto already_disabled;
0238 
0239     mic_set_path(mic, 0);
0240 
0241     pm_runtime_put(mic->dev);
0242     mic->enabled = 0;
0243 
0244 already_disabled:
0245     mutex_unlock(&mic_mutex);
0246 }
0247 
0248 static void mic_mode_set(struct drm_bridge *bridge,
0249              const struct drm_display_mode *mode,
0250              const struct drm_display_mode *adjusted_mode)
0251 {
0252     struct exynos_mic *mic = bridge->driver_private;
0253 
0254     mutex_lock(&mic_mutex);
0255     drm_display_mode_to_videomode(mode, &mic->vm);
0256     mic->i80_mode = to_exynos_crtc(bridge->encoder->crtc)->i80_mode;
0257     mutex_unlock(&mic_mutex);
0258 }
0259 
0260 static void mic_pre_enable(struct drm_bridge *bridge)
0261 {
0262     struct exynos_mic *mic = bridge->driver_private;
0263     int ret;
0264 
0265     mutex_lock(&mic_mutex);
0266     if (mic->enabled)
0267         goto unlock;
0268 
0269     ret = pm_runtime_resume_and_get(mic->dev);
0270     if (ret < 0)
0271         goto unlock;
0272 
0273     mic_set_path(mic, 1);
0274 
0275     ret = mic_sw_reset(mic);
0276     if (ret) {
0277         DRM_DEV_ERROR(mic->dev, "Failed to reset\n");
0278         goto turn_off;
0279     }
0280 
0281     if (!mic->i80_mode)
0282         mic_set_porch_timing(mic);
0283     mic_set_img_size(mic);
0284     mic_set_output_timing(mic);
0285     mic_set_reg_on(mic, 1);
0286     mic->enabled = 1;
0287     mutex_unlock(&mic_mutex);
0288 
0289     return;
0290 
0291 turn_off:
0292     pm_runtime_put(mic->dev);
0293 unlock:
0294     mutex_unlock(&mic_mutex);
0295 }
0296 
0297 static const struct drm_bridge_funcs mic_bridge_funcs = {
0298     .post_disable = mic_post_disable,
0299     .mode_set = mic_mode_set,
0300     .pre_enable = mic_pre_enable,
0301 };
0302 
0303 static int exynos_mic_bind(struct device *dev, struct device *master,
0304                void *data)
0305 {
0306     struct exynos_mic *mic = dev_get_drvdata(dev);
0307     struct drm_device *drm_dev = data;
0308     struct exynos_drm_crtc *crtc = exynos_drm_crtc_get_by_type(drm_dev,
0309                                EXYNOS_DISPLAY_TYPE_LCD);
0310     struct drm_encoder *e, *encoder = NULL;
0311 
0312     drm_for_each_encoder(e, drm_dev)
0313         if (e->possible_crtcs == drm_crtc_mask(&crtc->base))
0314             encoder = e;
0315     if (!encoder)
0316         return -ENODEV;
0317 
0318     mic->bridge.driver_private = mic;
0319 
0320     return drm_bridge_attach(encoder, &mic->bridge, NULL, 0);
0321 }
0322 
0323 static void exynos_mic_unbind(struct device *dev, struct device *master,
0324                   void *data)
0325 {
0326     struct exynos_mic *mic = dev_get_drvdata(dev);
0327 
0328     mutex_lock(&mic_mutex);
0329     if (!mic->enabled)
0330         goto already_disabled;
0331 
0332     pm_runtime_put(mic->dev);
0333 
0334 already_disabled:
0335     mutex_unlock(&mic_mutex);
0336 }
0337 
0338 static const struct component_ops exynos_mic_component_ops = {
0339     .bind   = exynos_mic_bind,
0340     .unbind = exynos_mic_unbind,
0341 };
0342 
0343 #ifdef CONFIG_PM
0344 static int exynos_mic_suspend(struct device *dev)
0345 {
0346     struct exynos_mic *mic = dev_get_drvdata(dev);
0347     int i;
0348 
0349     for (i = NUM_CLKS - 1; i > -1; i--)
0350         clk_disable_unprepare(mic->clks[i]);
0351 
0352     return 0;
0353 }
0354 
0355 static int exynos_mic_resume(struct device *dev)
0356 {
0357     struct exynos_mic *mic = dev_get_drvdata(dev);
0358     int ret, i;
0359 
0360     for (i = 0; i < NUM_CLKS; i++) {
0361         ret = clk_prepare_enable(mic->clks[i]);
0362         if (ret < 0) {
0363             DRM_DEV_ERROR(dev, "Failed to enable clock (%s)\n",
0364                       clk_names[i]);
0365             while (--i > -1)
0366                 clk_disable_unprepare(mic->clks[i]);
0367             return ret;
0368         }
0369     }
0370     return 0;
0371 }
0372 #endif
0373 
0374 static const struct dev_pm_ops exynos_mic_pm_ops = {
0375     SET_RUNTIME_PM_OPS(exynos_mic_suspend, exynos_mic_resume, NULL)
0376     SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
0377                 pm_runtime_force_resume)
0378 };
0379 
0380 static int exynos_mic_probe(struct platform_device *pdev)
0381 {
0382     struct device *dev = &pdev->dev;
0383     struct exynos_mic *mic;
0384     struct resource res;
0385     int ret, i;
0386 
0387     mic = devm_kzalloc(dev, sizeof(*mic), GFP_KERNEL);
0388     if (!mic) {
0389         DRM_DEV_ERROR(dev,
0390                   "mic: Failed to allocate memory for MIC object\n");
0391         ret = -ENOMEM;
0392         goto err;
0393     }
0394 
0395     mic->dev = dev;
0396 
0397     ret = of_address_to_resource(dev->of_node, 0, &res);
0398     if (ret) {
0399         DRM_DEV_ERROR(dev, "mic: Failed to get mem region for MIC\n");
0400         goto err;
0401     }
0402     mic->reg = devm_ioremap(dev, res.start, resource_size(&res));
0403     if (!mic->reg) {
0404         DRM_DEV_ERROR(dev, "mic: Failed to remap for MIC\n");
0405         ret = -ENOMEM;
0406         goto err;
0407     }
0408 
0409     mic->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
0410                             "samsung,disp-syscon");
0411     if (IS_ERR(mic->sysreg)) {
0412         DRM_DEV_ERROR(dev, "mic: Failed to get system register.\n");
0413         ret = PTR_ERR(mic->sysreg);
0414         goto err;
0415     }
0416 
0417     for (i = 0; i < NUM_CLKS; i++) {
0418         mic->clks[i] = devm_clk_get(dev, clk_names[i]);
0419         if (IS_ERR(mic->clks[i])) {
0420             DRM_DEV_ERROR(dev, "mic: Failed to get clock (%s)\n",
0421                       clk_names[i]);
0422             ret = PTR_ERR(mic->clks[i]);
0423             goto err;
0424         }
0425     }
0426 
0427     platform_set_drvdata(pdev, mic);
0428 
0429     mic->bridge.funcs = &mic_bridge_funcs;
0430     mic->bridge.of_node = dev->of_node;
0431 
0432     drm_bridge_add(&mic->bridge);
0433 
0434     pm_runtime_enable(dev);
0435 
0436     ret = component_add(dev, &exynos_mic_component_ops);
0437     if (ret)
0438         goto err_pm;
0439 
0440     DRM_DEV_DEBUG_KMS(dev, "MIC has been probed\n");
0441 
0442     return 0;
0443 
0444 err_pm:
0445     pm_runtime_disable(dev);
0446 err:
0447     return ret;
0448 }
0449 
0450 static int exynos_mic_remove(struct platform_device *pdev)
0451 {
0452     struct exynos_mic *mic = platform_get_drvdata(pdev);
0453 
0454     component_del(&pdev->dev, &exynos_mic_component_ops);
0455     pm_runtime_disable(&pdev->dev);
0456 
0457     drm_bridge_remove(&mic->bridge);
0458 
0459     return 0;
0460 }
0461 
0462 static const struct of_device_id exynos_mic_of_match[] = {
0463     { .compatible = "samsung,exynos5433-mic" },
0464     { }
0465 };
0466 MODULE_DEVICE_TABLE(of, exynos_mic_of_match);
0467 
0468 struct platform_driver mic_driver = {
0469     .probe      = exynos_mic_probe,
0470     .remove     = exynos_mic_remove,
0471     .driver     = {
0472         .name   = "exynos-mic",
0473         .pm = &exynos_mic_pm_ops,
0474         .owner  = THIS_MODULE,
0475         .of_match_table = exynos_mic_of_match,
0476     },
0477 };