0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/io.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/pm_runtime.h>
0013
0014 #include <drm/drm_color_mgmt.h>
0015
0016 #include "rcar_cmm.h"
0017
0018 #define CM2_LUT_CTRL 0x0000
0019 #define CM2_LUT_CTRL_LUT_EN BIT(0)
0020 #define CM2_LUT_TBL_BASE 0x0600
0021 #define CM2_LUT_TBL(__i) (CM2_LUT_TBL_BASE + (__i) * 4)
0022
0023 struct rcar_cmm {
0024 void __iomem *base;
0025
0026
0027
0028
0029
0030 struct {
0031 bool enabled;
0032 } lut;
0033 };
0034
0035 static inline int rcar_cmm_read(struct rcar_cmm *rcmm, u32 reg)
0036 {
0037 return ioread32(rcmm->base + reg);
0038 }
0039
0040 static inline void rcar_cmm_write(struct rcar_cmm *rcmm, u32 reg, u32 data)
0041 {
0042 iowrite32(data, rcmm->base + reg);
0043 }
0044
0045
0046
0047
0048
0049
0050
0051 static void rcar_cmm_lut_write(struct rcar_cmm *rcmm,
0052 const struct drm_color_lut *drm_lut)
0053 {
0054 unsigned int i;
0055
0056 for (i = 0; i < CM2_LUT_SIZE; ++i) {
0057 u32 entry = drm_color_lut_extract(drm_lut[i].red, 8) << 16
0058 | drm_color_lut_extract(drm_lut[i].green, 8) << 8
0059 | drm_color_lut_extract(drm_lut[i].blue, 8);
0060
0061 rcar_cmm_write(rcmm, CM2_LUT_TBL(i), entry);
0062 }
0063 }
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 int rcar_cmm_setup(struct platform_device *pdev,
0082 const struct rcar_cmm_config *config)
0083 {
0084 struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
0085
0086
0087 if (!config->lut.table) {
0088 if (rcmm->lut.enabled) {
0089 rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
0090 rcmm->lut.enabled = false;
0091 }
0092
0093 return 0;
0094 }
0095
0096
0097 if (!rcmm->lut.enabled) {
0098 rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
0099 rcmm->lut.enabled = true;
0100 }
0101
0102 rcar_cmm_lut_write(rcmm, config->lut.table);
0103
0104 return 0;
0105 }
0106 EXPORT_SYMBOL_GPL(rcar_cmm_setup);
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 int rcar_cmm_enable(struct platform_device *pdev)
0122 {
0123 int ret;
0124
0125 ret = pm_runtime_resume_and_get(&pdev->dev);
0126 if (ret < 0)
0127 return ret;
0128
0129 return 0;
0130 }
0131 EXPORT_SYMBOL_GPL(rcar_cmm_enable);
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143 void rcar_cmm_disable(struct platform_device *pdev)
0144 {
0145 struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
0146
0147 rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
0148 rcmm->lut.enabled = false;
0149
0150 pm_runtime_put(&pdev->dev);
0151 }
0152 EXPORT_SYMBOL_GPL(rcar_cmm_disable);
0153
0154
0155
0156
0157
0158
0159
0160
0161 int rcar_cmm_init(struct platform_device *pdev)
0162 {
0163 struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
0164
0165 if (!rcmm)
0166 return -EPROBE_DEFER;
0167
0168 return 0;
0169 }
0170 EXPORT_SYMBOL_GPL(rcar_cmm_init);
0171
0172 static int rcar_cmm_probe(struct platform_device *pdev)
0173 {
0174 struct rcar_cmm *rcmm;
0175
0176 rcmm = devm_kzalloc(&pdev->dev, sizeof(*rcmm), GFP_KERNEL);
0177 if (!rcmm)
0178 return -ENOMEM;
0179 platform_set_drvdata(pdev, rcmm);
0180
0181 rcmm->base = devm_platform_ioremap_resource(pdev, 0);
0182 if (IS_ERR(rcmm->base))
0183 return PTR_ERR(rcmm->base);
0184
0185 pm_runtime_enable(&pdev->dev);
0186
0187 return 0;
0188 }
0189
0190 static int rcar_cmm_remove(struct platform_device *pdev)
0191 {
0192 pm_runtime_disable(&pdev->dev);
0193
0194 return 0;
0195 }
0196
0197 static const struct of_device_id rcar_cmm_of_table[] = {
0198 { .compatible = "renesas,rcar-gen3-cmm", },
0199 { .compatible = "renesas,rcar-gen2-cmm", },
0200 { },
0201 };
0202 MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
0203
0204 static struct platform_driver rcar_cmm_platform_driver = {
0205 .probe = rcar_cmm_probe,
0206 .remove = rcar_cmm_remove,
0207 .driver = {
0208 .name = "rcar-cmm",
0209 .of_match_table = rcar_cmm_of_table,
0210 },
0211 };
0212
0213 module_platform_driver(rcar_cmm_platform_driver);
0214
0215 MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
0216 MODULE_DESCRIPTION("Renesas R-Car CMM Driver");
0217 MODULE_LICENSE("GPL v2");