root/drivers/gpu/drm/exynos/exynos_drm_mic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mic_set_path
  2. mic_sw_reset
  3. mic_set_porch_timing
  4. mic_set_img_size
  5. mic_set_output_timing
  6. mic_set_reg_on
  7. mic_disable
  8. mic_post_disable
  9. mic_mode_set
  10. mic_pre_enable
  11. mic_enable
  12. exynos_mic_bind
  13. exynos_mic_unbind
  14. exynos_mic_suspend
  15. exynos_mic_resume
  16. exynos_mic_probe
  17. exynos_mic_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2015 Samsung Electronics Co.Ltd
   4  * Authors:
   5  *      Hyungwon Hwang <human.hwang@samsung.com>
   6  */
   7 
   8 #include <linux/clk.h>
   9 #include <linux/component.h>
  10 #include <linux/delay.h>
  11 #include <linux/mfd/syscon.h>
  12 #include <linux/module.h>
  13 #include <linux/mutex.h>
  14 #include <linux/of.h>
  15 #include <linux/of_address.h>
  16 #include <linux/of_graph.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/pm_runtime.h>
  19 #include <linux/regmap.h>
  20 
  21 #include <video/of_videomode.h>
  22 #include <video/videomode.h>
  23 
  24 #include <drm/drm_encoder.h>
  25 #include <drm/drm_print.h>
  26 
  27 #include "exynos_drm_drv.h"
  28 
  29 /* Sysreg registers for MIC */
  30 #define DSD_CFG_MUX     0x1004
  31 #define MIC0_RGB_MUX    (1 << 0)
  32 #define MIC0_I80_MUX    (1 << 1)
  33 #define MIC0_ON_MUX     (1 << 5)
  34 
  35 /* MIC registers */
  36 #define MIC_OP                          0x0
  37 #define MIC_IP_VER                      0x0004
  38 #define MIC_V_TIMING_0                  0x0008
  39 #define MIC_V_TIMING_1                  0x000C
  40 #define MIC_IMG_SIZE                    0x0010
  41 #define MIC_INPUT_TIMING_0              0x0014
  42 #define MIC_INPUT_TIMING_1              0x0018
  43 #define MIC_2D_OUTPUT_TIMING_0          0x001C
  44 #define MIC_2D_OUTPUT_TIMING_1          0x0020
  45 #define MIC_2D_OUTPUT_TIMING_2          0x0024
  46 #define MIC_3D_OUTPUT_TIMING_0          0x0028
  47 #define MIC_3D_OUTPUT_TIMING_1          0x002C
  48 #define MIC_3D_OUTPUT_TIMING_2          0x0030
  49 #define MIC_CORE_PARA_0                 0x0034
  50 #define MIC_CORE_PARA_1                 0x0038
  51 #define MIC_CTC_CTRL                    0x0040
  52 #define MIC_RD_DATA                     0x0044
  53 
  54 #define MIC_UPD_REG                     (1 << 31)
  55 #define MIC_ON_REG                      (1 << 30)
  56 #define MIC_TD_ON_REG                   (1 << 29)
  57 #define MIC_BS_CHG_OUT                  (1 << 16)
  58 #define MIC_VIDEO_TYPE(x)               (((x) & 0xf) << 12)
  59 #define MIC_PSR_EN                      (1 << 5)
  60 #define MIC_SW_RST                      (1 << 4)
  61 #define MIC_ALL_RST                     (1 << 3)
  62 #define MIC_CORE_VER_CONTROL            (1 << 2)
  63 #define MIC_MODE_SEL_COMMAND_MODE       (1 << 1)
  64 #define MIC_MODE_SEL_MASK               (1 << 1)
  65 #define MIC_CORE_EN                     (1 << 0)
  66 
  67 #define MIC_V_PULSE_WIDTH(x)            (((x) & 0x3fff) << 16)
  68 #define MIC_V_PERIOD_LINE(x)            ((x) & 0x3fff)
  69 
  70 #define MIC_VBP_SIZE(x)                 (((x) & 0x3fff) << 16)
  71 #define MIC_VFP_SIZE(x)                 ((x) & 0x3fff)
  72 
  73 #define MIC_IMG_V_SIZE(x)               (((x) & 0x3fff) << 16)
  74 #define MIC_IMG_H_SIZE(x)               ((x) & 0x3fff)
  75 
  76 #define MIC_H_PULSE_WIDTH_IN(x)         (((x) & 0x3fff) << 16)
  77 #define MIC_H_PERIOD_PIXEL_IN(x)        ((x) & 0x3fff)
  78 
  79 #define MIC_HBP_SIZE_IN(x)              (((x) & 0x3fff) << 16)
  80 #define MIC_HFP_SIZE_IN(x)              ((x) & 0x3fff)
  81 
  82 #define MIC_H_PULSE_WIDTH_2D(x)         (((x) & 0x3fff) << 16)
  83 #define MIC_H_PERIOD_PIXEL_2D(x)        ((x) & 0x3fff)
  84 
  85 #define MIC_HBP_SIZE_2D(x)              (((x) & 0x3fff) << 16)
  86 #define MIC_HFP_SIZE_2D(x)              ((x) & 0x3fff)
  87 
  88 #define MIC_BS_SIZE_2D(x)       ((x) & 0x3fff)
  89 
  90 static char *clk_names[] = { "pclk_mic0", "sclk_rgb_vclk_to_mic0" };
  91 #define NUM_CLKS                ARRAY_SIZE(clk_names)
  92 static DEFINE_MUTEX(mic_mutex);
  93 
  94 struct exynos_mic {
  95         struct device *dev;
  96         void __iomem *reg;
  97         struct regmap *sysreg;
  98         struct clk *clks[NUM_CLKS];
  99 
 100         bool i80_mode;
 101         struct videomode vm;
 102         struct drm_encoder *encoder;
 103         struct drm_bridge bridge;
 104 
 105         bool enabled;
 106 };
 107 
 108 static void mic_set_path(struct exynos_mic *mic, bool enable)
 109 {
 110         int ret;
 111         unsigned int val;
 112 
 113         ret = regmap_read(mic->sysreg, DSD_CFG_MUX, &val);
 114         if (ret) {
 115                 DRM_DEV_ERROR(mic->dev,
 116                               "mic: Failed to read system register\n");
 117                 return;
 118         }
 119 
 120         if (enable) {
 121                 if (mic->i80_mode)
 122                         val |= MIC0_I80_MUX;
 123                 else
 124                         val |= MIC0_RGB_MUX;
 125 
 126                 val |=  MIC0_ON_MUX;
 127         } else
 128                 val &= ~(MIC0_RGB_MUX | MIC0_I80_MUX | MIC0_ON_MUX);
 129 
 130         ret = regmap_write(mic->sysreg, DSD_CFG_MUX, val);
 131         if (ret)
 132                 DRM_DEV_ERROR(mic->dev,
 133                               "mic: Failed to read system register\n");
 134 }
 135 
 136 static int mic_sw_reset(struct exynos_mic *mic)
 137 {
 138         unsigned int retry = 100;
 139         int ret;
 140 
 141         writel(MIC_SW_RST, mic->reg + MIC_OP);
 142 
 143         while (retry-- > 0) {
 144                 ret = readl(mic->reg + MIC_OP);
 145                 if (!(ret & MIC_SW_RST))
 146                         return 0;
 147 
 148                 udelay(10);
 149         }
 150 
 151         return -ETIMEDOUT;
 152 }
 153 
 154 static void mic_set_porch_timing(struct exynos_mic *mic)
 155 {
 156         struct videomode vm = mic->vm;
 157         u32 reg;
 158 
 159         reg = MIC_V_PULSE_WIDTH(vm.vsync_len) +
 160                 MIC_V_PERIOD_LINE(vm.vsync_len + vm.vactive +
 161                                 vm.vback_porch + vm.vfront_porch);
 162         writel(reg, mic->reg + MIC_V_TIMING_0);
 163 
 164         reg = MIC_VBP_SIZE(vm.vback_porch) +
 165                 MIC_VFP_SIZE(vm.vfront_porch);
 166         writel(reg, mic->reg + MIC_V_TIMING_1);
 167 
 168         reg = MIC_V_PULSE_WIDTH(vm.hsync_len) +
 169                 MIC_V_PERIOD_LINE(vm.hsync_len + vm.hactive +
 170                                 vm.hback_porch + vm.hfront_porch);
 171         writel(reg, mic->reg + MIC_INPUT_TIMING_0);
 172 
 173         reg = MIC_VBP_SIZE(vm.hback_porch) +
 174                 MIC_VFP_SIZE(vm.hfront_porch);
 175         writel(reg, mic->reg + MIC_INPUT_TIMING_1);
 176 }
 177 
 178 static void mic_set_img_size(struct exynos_mic *mic)
 179 {
 180         struct videomode *vm = &mic->vm;
 181         u32 reg;
 182 
 183         reg = MIC_IMG_H_SIZE(vm->hactive) +
 184                 MIC_IMG_V_SIZE(vm->vactive);
 185 
 186         writel(reg, mic->reg + MIC_IMG_SIZE);
 187 }
 188 
 189 static void mic_set_output_timing(struct exynos_mic *mic)
 190 {
 191         struct videomode vm = mic->vm;
 192         u32 reg, bs_size_2d;
 193 
 194         DRM_DEV_DEBUG(mic->dev, "w: %u, h: %u\n", vm.hactive, vm.vactive);
 195         bs_size_2d = ((vm.hactive >> 2) << 1) + (vm.vactive % 4);
 196         reg = MIC_BS_SIZE_2D(bs_size_2d);
 197         writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_2);
 198 
 199         if (!mic->i80_mode) {
 200                 reg = MIC_H_PULSE_WIDTH_2D(vm.hsync_len) +
 201                         MIC_H_PERIOD_PIXEL_2D(vm.hsync_len + bs_size_2d +
 202                                         vm.hback_porch + vm.hfront_porch);
 203                 writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_0);
 204 
 205                 reg = MIC_HBP_SIZE_2D(vm.hback_porch) +
 206                         MIC_H_PERIOD_PIXEL_2D(vm.hfront_porch);
 207                 writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_1);
 208         }
 209 }
 210 
 211 static void mic_set_reg_on(struct exynos_mic *mic, bool enable)
 212 {
 213         u32 reg = readl(mic->reg + MIC_OP);
 214 
 215         if (enable) {
 216                 reg &= ~(MIC_MODE_SEL_MASK | MIC_CORE_VER_CONTROL | MIC_PSR_EN);
 217                 reg |= (MIC_CORE_EN | MIC_BS_CHG_OUT | MIC_ON_REG);
 218 
 219                 reg  &= ~MIC_MODE_SEL_COMMAND_MODE;
 220                 if (mic->i80_mode)
 221                         reg |= MIC_MODE_SEL_COMMAND_MODE;
 222         } else {
 223                 reg &= ~MIC_CORE_EN;
 224         }
 225 
 226         reg |= MIC_UPD_REG;
 227         writel(reg, mic->reg + MIC_OP);
 228 }
 229 
 230 static void mic_disable(struct drm_bridge *bridge) { }
 231 
 232 static void mic_post_disable(struct drm_bridge *bridge)
 233 {
 234         struct exynos_mic *mic = bridge->driver_private;
 235 
 236         mutex_lock(&mic_mutex);
 237         if (!mic->enabled)
 238                 goto already_disabled;
 239 
 240         mic_set_path(mic, 0);
 241 
 242         pm_runtime_put(mic->dev);
 243         mic->enabled = 0;
 244 
 245 already_disabled:
 246         mutex_unlock(&mic_mutex);
 247 }
 248 
 249 static void mic_mode_set(struct drm_bridge *bridge,
 250                          const struct drm_display_mode *mode,
 251                          const struct drm_display_mode *adjusted_mode)
 252 {
 253         struct exynos_mic *mic = bridge->driver_private;
 254 
 255         mutex_lock(&mic_mutex);
 256         drm_display_mode_to_videomode(mode, &mic->vm);
 257         mic->i80_mode = to_exynos_crtc(bridge->encoder->crtc)->i80_mode;
 258         mutex_unlock(&mic_mutex);
 259 }
 260 
 261 static void mic_pre_enable(struct drm_bridge *bridge)
 262 {
 263         struct exynos_mic *mic = bridge->driver_private;
 264         int ret;
 265 
 266         mutex_lock(&mic_mutex);
 267         if (mic->enabled)
 268                 goto unlock;
 269 
 270         ret = pm_runtime_get_sync(mic->dev);
 271         if (ret < 0)
 272                 goto unlock;
 273 
 274         mic_set_path(mic, 1);
 275 
 276         ret = mic_sw_reset(mic);
 277         if (ret) {
 278                 DRM_DEV_ERROR(mic->dev, "Failed to reset\n");
 279                 goto turn_off;
 280         }
 281 
 282         if (!mic->i80_mode)
 283                 mic_set_porch_timing(mic);
 284         mic_set_img_size(mic);
 285         mic_set_output_timing(mic);
 286         mic_set_reg_on(mic, 1);
 287         mic->enabled = 1;
 288         mutex_unlock(&mic_mutex);
 289 
 290         return;
 291 
 292 turn_off:
 293         pm_runtime_put(mic->dev);
 294 unlock:
 295         mutex_unlock(&mic_mutex);
 296 }
 297 
 298 static void mic_enable(struct drm_bridge *bridge) { }
 299 
 300 static const struct drm_bridge_funcs mic_bridge_funcs = {
 301         .disable = mic_disable,
 302         .post_disable = mic_post_disable,
 303         .mode_set = mic_mode_set,
 304         .pre_enable = mic_pre_enable,
 305         .enable = mic_enable,
 306 };
 307 
 308 static int exynos_mic_bind(struct device *dev, struct device *master,
 309                            void *data)
 310 {
 311         struct exynos_mic *mic = dev_get_drvdata(dev);
 312 
 313         mic->bridge.driver_private = mic;
 314 
 315         return 0;
 316 }
 317 
 318 static void exynos_mic_unbind(struct device *dev, struct device *master,
 319                               void *data)
 320 {
 321         struct exynos_mic *mic = dev_get_drvdata(dev);
 322 
 323         mutex_lock(&mic_mutex);
 324         if (!mic->enabled)
 325                 goto already_disabled;
 326 
 327         pm_runtime_put(mic->dev);
 328 
 329 already_disabled:
 330         mutex_unlock(&mic_mutex);
 331 }
 332 
 333 static const struct component_ops exynos_mic_component_ops = {
 334         .bind   = exynos_mic_bind,
 335         .unbind = exynos_mic_unbind,
 336 };
 337 
 338 #ifdef CONFIG_PM
 339 static int exynos_mic_suspend(struct device *dev)
 340 {
 341         struct exynos_mic *mic = dev_get_drvdata(dev);
 342         int i;
 343 
 344         for (i = NUM_CLKS - 1; i > -1; i--)
 345                 clk_disable_unprepare(mic->clks[i]);
 346 
 347         return 0;
 348 }
 349 
 350 static int exynos_mic_resume(struct device *dev)
 351 {
 352         struct exynos_mic *mic = dev_get_drvdata(dev);
 353         int ret, i;
 354 
 355         for (i = 0; i < NUM_CLKS; i++) {
 356                 ret = clk_prepare_enable(mic->clks[i]);
 357                 if (ret < 0) {
 358                         DRM_DEV_ERROR(dev, "Failed to enable clock (%s)\n",
 359                                       clk_names[i]);
 360                         while (--i > -1)
 361                                 clk_disable_unprepare(mic->clks[i]);
 362                         return ret;
 363                 }
 364         }
 365         return 0;
 366 }
 367 #endif
 368 
 369 static const struct dev_pm_ops exynos_mic_pm_ops = {
 370         SET_RUNTIME_PM_OPS(exynos_mic_suspend, exynos_mic_resume, NULL)
 371         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
 372                                 pm_runtime_force_resume)
 373 };
 374 
 375 static int exynos_mic_probe(struct platform_device *pdev)
 376 {
 377         struct device *dev = &pdev->dev;
 378         struct exynos_mic *mic;
 379         struct resource res;
 380         int ret, i;
 381 
 382         mic = devm_kzalloc(dev, sizeof(*mic), GFP_KERNEL);
 383         if (!mic) {
 384                 DRM_DEV_ERROR(dev,
 385                               "mic: Failed to allocate memory for MIC object\n");
 386                 ret = -ENOMEM;
 387                 goto err;
 388         }
 389 
 390         mic->dev = dev;
 391 
 392         ret = of_address_to_resource(dev->of_node, 0, &res);
 393         if (ret) {
 394                 DRM_DEV_ERROR(dev, "mic: Failed to get mem region for MIC\n");
 395                 goto err;
 396         }
 397         mic->reg = devm_ioremap(dev, res.start, resource_size(&res));
 398         if (!mic->reg) {
 399                 DRM_DEV_ERROR(dev, "mic: Failed to remap for MIC\n");
 400                 ret = -ENOMEM;
 401                 goto err;
 402         }
 403 
 404         mic->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
 405                                                         "samsung,disp-syscon");
 406         if (IS_ERR(mic->sysreg)) {
 407                 DRM_DEV_ERROR(dev, "mic: Failed to get system register.\n");
 408                 ret = PTR_ERR(mic->sysreg);
 409                 goto err;
 410         }
 411 
 412         for (i = 0; i < NUM_CLKS; i++) {
 413                 mic->clks[i] = devm_clk_get(dev, clk_names[i]);
 414                 if (IS_ERR(mic->clks[i])) {
 415                         DRM_DEV_ERROR(dev, "mic: Failed to get clock (%s)\n",
 416                                       clk_names[i]);
 417                         ret = PTR_ERR(mic->clks[i]);
 418                         goto err;
 419                 }
 420         }
 421 
 422         platform_set_drvdata(pdev, mic);
 423 
 424         mic->bridge.funcs = &mic_bridge_funcs;
 425         mic->bridge.of_node = dev->of_node;
 426 
 427         drm_bridge_add(&mic->bridge);
 428 
 429         pm_runtime_enable(dev);
 430 
 431         ret = component_add(dev, &exynos_mic_component_ops);
 432         if (ret)
 433                 goto err_pm;
 434 
 435         DRM_DEV_DEBUG_KMS(dev, "MIC has been probed\n");
 436 
 437         return 0;
 438 
 439 err_pm:
 440         pm_runtime_disable(dev);
 441 err:
 442         return ret;
 443 }
 444 
 445 static int exynos_mic_remove(struct platform_device *pdev)
 446 {
 447         struct exynos_mic *mic = platform_get_drvdata(pdev);
 448 
 449         component_del(&pdev->dev, &exynos_mic_component_ops);
 450         pm_runtime_disable(&pdev->dev);
 451 
 452         drm_bridge_remove(&mic->bridge);
 453 
 454         return 0;
 455 }
 456 
 457 static const struct of_device_id exynos_mic_of_match[] = {
 458         { .compatible = "samsung,exynos5433-mic" },
 459         { }
 460 };
 461 MODULE_DEVICE_TABLE(of, exynos_mic_of_match);
 462 
 463 struct platform_driver mic_driver = {
 464         .probe          = exynos_mic_probe,
 465         .remove         = exynos_mic_remove,
 466         .driver         = {
 467                 .name   = "exynos-mic",
 468                 .pm     = &exynos_mic_pm_ops,
 469                 .owner  = THIS_MODULE,
 470                 .of_match_table = exynos_mic_of_match,
 471         },
 472 };

/* [<][>][^][v][top][bottom][index][help] */