0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008
0009 #include <drm/drm_atomic_helper.h>
0010 #include <drm/drm_bridge_connector.h>
0011 #include <drm/drm_simple_kms_helper.h>
0012
0013 #include "drm.h"
0014 #include "dc.h"
0015
0016 struct tegra_rgb {
0017 struct tegra_output output;
0018 struct tegra_dc *dc;
0019
0020 struct clk *pll_d_out0;
0021 struct clk *pll_d2_out0;
0022 struct clk *clk_parent;
0023 struct clk *clk;
0024 };
0025
0026 static inline struct tegra_rgb *to_rgb(struct tegra_output *output)
0027 {
0028 return container_of(output, struct tegra_rgb, output);
0029 }
0030
0031 struct reg_entry {
0032 unsigned long offset;
0033 unsigned long value;
0034 };
0035
0036 static const struct reg_entry rgb_enable[] = {
0037 { DC_COM_PIN_OUTPUT_ENABLE(0), 0x00000000 },
0038 { DC_COM_PIN_OUTPUT_ENABLE(1), 0x00000000 },
0039 { DC_COM_PIN_OUTPUT_ENABLE(2), 0x00000000 },
0040 { DC_COM_PIN_OUTPUT_ENABLE(3), 0x00000000 },
0041 { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
0042 { DC_COM_PIN_OUTPUT_POLARITY(1), 0x01000000 },
0043 { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
0044 { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
0045 { DC_COM_PIN_OUTPUT_DATA(0), 0x00000000 },
0046 { DC_COM_PIN_OUTPUT_DATA(1), 0x00000000 },
0047 { DC_COM_PIN_OUTPUT_DATA(2), 0x00000000 },
0048 { DC_COM_PIN_OUTPUT_DATA(3), 0x00000000 },
0049 { DC_COM_PIN_OUTPUT_SELECT(0), 0x00000000 },
0050 { DC_COM_PIN_OUTPUT_SELECT(1), 0x00000000 },
0051 { DC_COM_PIN_OUTPUT_SELECT(2), 0x00000000 },
0052 { DC_COM_PIN_OUTPUT_SELECT(3), 0x00000000 },
0053 { DC_COM_PIN_OUTPUT_SELECT(4), 0x00210222 },
0054 { DC_COM_PIN_OUTPUT_SELECT(5), 0x00002200 },
0055 { DC_COM_PIN_OUTPUT_SELECT(6), 0x00020000 },
0056 };
0057
0058 static const struct reg_entry rgb_disable[] = {
0059 { DC_COM_PIN_OUTPUT_SELECT(6), 0x00000000 },
0060 { DC_COM_PIN_OUTPUT_SELECT(5), 0x00000000 },
0061 { DC_COM_PIN_OUTPUT_SELECT(4), 0x00000000 },
0062 { DC_COM_PIN_OUTPUT_SELECT(3), 0x00000000 },
0063 { DC_COM_PIN_OUTPUT_SELECT(2), 0x00000000 },
0064 { DC_COM_PIN_OUTPUT_SELECT(1), 0x00000000 },
0065 { DC_COM_PIN_OUTPUT_SELECT(0), 0x00000000 },
0066 { DC_COM_PIN_OUTPUT_DATA(3), 0xaaaaaaaa },
0067 { DC_COM_PIN_OUTPUT_DATA(2), 0xaaaaaaaa },
0068 { DC_COM_PIN_OUTPUT_DATA(1), 0xaaaaaaaa },
0069 { DC_COM_PIN_OUTPUT_DATA(0), 0xaaaaaaaa },
0070 { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
0071 { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
0072 { DC_COM_PIN_OUTPUT_POLARITY(1), 0x00000000 },
0073 { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
0074 { DC_COM_PIN_OUTPUT_ENABLE(3), 0x55555555 },
0075 { DC_COM_PIN_OUTPUT_ENABLE(2), 0x55555555 },
0076 { DC_COM_PIN_OUTPUT_ENABLE(1), 0x55150005 },
0077 { DC_COM_PIN_OUTPUT_ENABLE(0), 0x55555555 },
0078 };
0079
0080 static void tegra_dc_write_regs(struct tegra_dc *dc,
0081 const struct reg_entry *table,
0082 unsigned int num)
0083 {
0084 unsigned int i;
0085
0086 for (i = 0; i < num; i++)
0087 tegra_dc_writel(dc, table[i].value, table[i].offset);
0088 }
0089
0090 static void tegra_rgb_encoder_disable(struct drm_encoder *encoder)
0091 {
0092 struct tegra_output *output = encoder_to_output(encoder);
0093 struct tegra_rgb *rgb = to_rgb(output);
0094
0095 tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
0096 tegra_dc_commit(rgb->dc);
0097 }
0098
0099 static void tegra_rgb_encoder_enable(struct drm_encoder *encoder)
0100 {
0101 struct tegra_output *output = encoder_to_output(encoder);
0102 struct tegra_rgb *rgb = to_rgb(output);
0103 u32 value;
0104
0105 tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
0106
0107 value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
0108 tegra_dc_writel(rgb->dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
0109
0110
0111 value = tegra_dc_readl(rgb->dc, DC_COM_PIN_OUTPUT_POLARITY(1));
0112 value &= ~LVS_OUTPUT_POLARITY_LOW;
0113 value &= ~LHS_OUTPUT_POLARITY_LOW;
0114 tegra_dc_writel(rgb->dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
0115
0116
0117 value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
0118 DISP_ORDER_RED_BLUE;
0119 tegra_dc_writel(rgb->dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
0120
0121 tegra_dc_commit(rgb->dc);
0122 }
0123
0124 static bool tegra_rgb_pll_rate_change_allowed(struct tegra_rgb *rgb)
0125 {
0126 if (!rgb->pll_d2_out0)
0127 return false;
0128
0129 if (!clk_is_match(rgb->clk_parent, rgb->pll_d_out0) &&
0130 !clk_is_match(rgb->clk_parent, rgb->pll_d2_out0))
0131 return false;
0132
0133 return true;
0134 }
0135
0136 static int
0137 tegra_rgb_encoder_atomic_check(struct drm_encoder *encoder,
0138 struct drm_crtc_state *crtc_state,
0139 struct drm_connector_state *conn_state)
0140 {
0141 struct tegra_output *output = encoder_to_output(encoder);
0142 struct tegra_dc *dc = to_tegra_dc(conn_state->crtc);
0143 unsigned long pclk = crtc_state->mode.clock * 1000;
0144 struct tegra_rgb *rgb = to_rgb(output);
0145 unsigned int div;
0146 int err;
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 if (tegra_rgb_pll_rate_change_allowed(rgb)) {
0165
0166
0167
0168
0169 div = 2;
0170 pclk *= 2;
0171 } else {
0172 div = ((clk_get_rate(rgb->clk) * 2) / pclk) - 2;
0173 pclk = 0;
0174 }
0175
0176 err = tegra_dc_state_setup_clock(dc, crtc_state, rgb->clk_parent,
0177 pclk, div);
0178 if (err < 0) {
0179 dev_err(output->dev, "failed to setup CRTC state: %d\n", err);
0180 return err;
0181 }
0182
0183 return err;
0184 }
0185
0186 static const struct drm_encoder_helper_funcs tegra_rgb_encoder_helper_funcs = {
0187 .disable = tegra_rgb_encoder_disable,
0188 .enable = tegra_rgb_encoder_enable,
0189 .atomic_check = tegra_rgb_encoder_atomic_check,
0190 };
0191
0192 int tegra_dc_rgb_probe(struct tegra_dc *dc)
0193 {
0194 struct device_node *np;
0195 struct tegra_rgb *rgb;
0196 int err;
0197
0198 np = of_get_child_by_name(dc->dev->of_node, "rgb");
0199 if (!np || !of_device_is_available(np))
0200 return -ENODEV;
0201
0202 rgb = devm_kzalloc(dc->dev, sizeof(*rgb), GFP_KERNEL);
0203 if (!rgb)
0204 return -ENOMEM;
0205
0206 rgb->output.dev = dc->dev;
0207 rgb->output.of_node = np;
0208 rgb->dc = dc;
0209
0210 err = tegra_output_probe(&rgb->output);
0211 if (err < 0)
0212 return err;
0213
0214 rgb->clk = devm_clk_get(dc->dev, NULL);
0215 if (IS_ERR(rgb->clk)) {
0216 dev_err(dc->dev, "failed to get clock\n");
0217 return PTR_ERR(rgb->clk);
0218 }
0219
0220 rgb->clk_parent = devm_clk_get(dc->dev, "parent");
0221 if (IS_ERR(rgb->clk_parent)) {
0222 dev_err(dc->dev, "failed to get parent clock\n");
0223 return PTR_ERR(rgb->clk_parent);
0224 }
0225
0226 err = clk_set_parent(rgb->clk, rgb->clk_parent);
0227 if (err < 0) {
0228 dev_err(dc->dev, "failed to set parent clock: %d\n", err);
0229 return err;
0230 }
0231
0232 rgb->pll_d_out0 = clk_get_sys(NULL, "pll_d_out0");
0233 if (IS_ERR(rgb->pll_d_out0)) {
0234 err = PTR_ERR(rgb->pll_d_out0);
0235 dev_err(dc->dev, "failed to get pll_d_out0: %d\n", err);
0236 return err;
0237 }
0238
0239 if (dc->soc->has_pll_d2_out0) {
0240 rgb->pll_d2_out0 = clk_get_sys(NULL, "pll_d2_out0");
0241 if (IS_ERR(rgb->pll_d2_out0)) {
0242 err = PTR_ERR(rgb->pll_d2_out0);
0243 dev_err(dc->dev, "failed to get pll_d2_out0: %d\n", err);
0244 return err;
0245 }
0246 }
0247
0248 dc->rgb = &rgb->output;
0249
0250 return 0;
0251 }
0252
0253 int tegra_dc_rgb_remove(struct tegra_dc *dc)
0254 {
0255 struct tegra_rgb *rgb;
0256
0257 if (!dc->rgb)
0258 return 0;
0259
0260 rgb = to_rgb(dc->rgb);
0261 clk_put(rgb->pll_d2_out0);
0262 clk_put(rgb->pll_d_out0);
0263
0264 tegra_output_remove(dc->rgb);
0265 dc->rgb = NULL;
0266
0267 return 0;
0268 }
0269
0270 int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
0271 {
0272 struct tegra_output *output = dc->rgb;
0273 struct drm_connector *connector;
0274 int err;
0275
0276 if (!dc->rgb)
0277 return -ENODEV;
0278
0279 drm_simple_encoder_init(drm, &output->encoder, DRM_MODE_ENCODER_LVDS);
0280 drm_encoder_helper_add(&output->encoder,
0281 &tegra_rgb_encoder_helper_funcs);
0282
0283
0284
0285
0286
0287 if (output->panel) {
0288 output->bridge = devm_drm_panel_bridge_add(output->dev,
0289 output->panel);
0290 if (IS_ERR(output->bridge)) {
0291 dev_err(output->dev,
0292 "failed to wrap panel into bridge: %pe\n",
0293 output->bridge);
0294 return PTR_ERR(output->bridge);
0295 }
0296
0297 output->panel = NULL;
0298 }
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316 if (output->bridge) {
0317 err = drm_bridge_attach(&output->encoder, output->bridge,
0318 NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
0319 if (err)
0320 return err;
0321
0322 connector = drm_bridge_connector_init(drm, &output->encoder);
0323 if (IS_ERR(connector)) {
0324 dev_err(output->dev,
0325 "failed to initialize bridge connector: %pe\n",
0326 connector);
0327 return PTR_ERR(connector);
0328 }
0329
0330 drm_connector_attach_encoder(connector, &output->encoder);
0331 }
0332
0333 err = tegra_output_init(drm, output);
0334 if (err < 0) {
0335 dev_err(output->dev, "failed to initialize output: %d\n", err);
0336 return err;
0337 }
0338
0339
0340
0341
0342
0343
0344 output->encoder.possible_crtcs = drm_crtc_mask(&dc->base);
0345
0346 return 0;
0347 }
0348
0349 int tegra_dc_rgb_exit(struct tegra_dc *dc)
0350 {
0351 if (dc->rgb)
0352 tegra_output_exit(dc->rgb);
0353
0354 return 0;
0355 }