Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2012 Avionic Design GmbH
0004  * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
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     /* XXX: parameterize? */
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     /* XXX: parameterize? */
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      * We may not want to change the frequency of the parent clock, since
0150      * it may be a parent for other peripherals. This is due to the fact
0151      * that on Tegra20 there's only a single clock dedicated to display
0152      * (pll_d_out0), whereas later generations have a second one that can
0153      * be used to independently drive a second output (pll_d2_out0).
0154      *
0155      * As a way to support multiple outputs on Tegra20 as well, pll_p is
0156      * typically used as the parent clock for the display controllers.
0157      * But this comes at a cost: pll_p is the parent of several other
0158      * peripherals, so its frequency shouldn't change out of the blue.
0159      *
0160      * The best we can do at this point is to use the shift clock divider
0161      * and hope that the desired frequency can be matched (or at least
0162      * matched sufficiently close that the panel will still work).
0163      */
0164     if (tegra_rgb_pll_rate_change_allowed(rgb)) {
0165         /*
0166          * Set display controller clock to x2 of PCLK in order to
0167          * produce higher resolution pulse positions.
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      * Wrap directly-connected panel into DRM bridge in order to let
0285      * DRM core to handle panel for us.
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      * Tegra devices that have LVDS panel utilize LVDS encoder bridge
0302      * for converting up to 28 LCD LVTTL lanes into 5/4 LVDS lanes that
0303      * go to display panel's receiver.
0304      *
0305      * Encoder usually have a power-down control which needs to be enabled
0306      * in order to transmit data to the panel.  Historically devices that
0307      * use an older device-tree version didn't model the bridge, assuming
0308      * that encoder is turned ON by default, while today's DRM allows us
0309      * to model LVDS encoder properly.
0310      *
0311      * Newer device-trees utilize LVDS encoder bridge, which provides
0312      * us with a connector and handles the display panel.
0313      *
0314      * For older device-trees we wrapped panel into the panel-bridge.
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      * Other outputs can be attached to either display controller. The RGB
0341      * outputs are an exception and work only with their parent display
0342      * controller.
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 }