sun8i_csc.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net>
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of
  7. * the License, or (at your option) any later version.
  8. */
  9. #include <drm/drmP.h>
  10. #include "sun8i_csc.h"
  11. #include "sun8i_mixer.h"
  12. static const u32 ccsc_base[2][2] = {
  13. {CCSC00_OFFSET, CCSC01_OFFSET},
  14. {CCSC10_OFFSET, CCSC11_OFFSET},
  15. };
  16. /*
  17. * Factors are in two's complement format, 10 bits for fractinal part.
  18. * First tree values in each line are multiplication factor and last
  19. * value is constant, which is added at the end.
  20. */
  21. static const u32 yuv2rgb[] = {
  22. 0x000004A8, 0x00000000, 0x00000662, 0xFFFC845A,
  23. 0x000004A8, 0xFFFFFE6F, 0xFFFFFCBF, 0x00021DF4,
  24. 0x000004A8, 0x00000813, 0x00000000, 0xFFFBAC4A,
  25. };
  26. static const u32 yvu2rgb[] = {
  27. 0x000004A8, 0x00000662, 0x00000000, 0xFFFC845A,
  28. 0x000004A8, 0xFFFFFCBF, 0xFFFFFE6F, 0x00021DF4,
  29. 0x000004A8, 0x00000000, 0x00000813, 0xFFFBAC4A,
  30. };
  31. static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
  32. enum sun8i_csc_mode mode)
  33. {
  34. const u32 *table;
  35. int i, data;
  36. switch (mode) {
  37. case SUN8I_CSC_MODE_YUV2RGB:
  38. table = yuv2rgb;
  39. break;
  40. case SUN8I_CSC_MODE_YVU2RGB:
  41. table = yvu2rgb;
  42. break;
  43. default:
  44. DRM_WARN("Wrong CSC mode specified.\n");
  45. return;
  46. }
  47. for (i = 0; i < 12; i++) {
  48. data = table[i];
  49. /* For some reason, 0x200 must be added to constant parts */
  50. if (((i + 1) & 3) == 0)
  51. data += 0x200;
  52. regmap_write(map, SUN8I_CSC_COEFF(base, i), data);
  53. }
  54. }
  55. static void sun8i_csc_enable(struct regmap *map, u32 base, bool enable)
  56. {
  57. u32 val;
  58. if (enable)
  59. val = SUN8I_CSC_CTRL_EN;
  60. else
  61. val = 0;
  62. regmap_update_bits(map, SUN8I_CSC_CTRL(base), SUN8I_CSC_CTRL_EN, val);
  63. }
  64. void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
  65. enum sun8i_csc_mode mode)
  66. {
  67. u32 base;
  68. base = ccsc_base[mixer->cfg->ccsc][layer];
  69. sun8i_csc_set_coefficients(mixer->engine.regs, base, mode);
  70. }
  71. void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable)
  72. {
  73. u32 base;
  74. base = ccsc_base[mixer->cfg->ccsc][layer];
  75. sun8i_csc_enable(mixer->engine.regs, base, enable);
  76. }