195 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.4 */5 6#include <linux/of_graph.h>7 8#include "adv7511.h"9 10static const struct reg_sequence adv7533_fixed_registers[] = {11 { 0x16, 0x20 },12 { 0x9a, 0xe0 },13 { 0xba, 0x70 },14 { 0xde, 0x82 },15 { 0xe4, 0x40 },16 { 0xe5, 0x80 },17};18 19static const struct reg_sequence adv7533_cec_fixed_registers[] = {20 { 0x15, 0xd0 },21 { 0x17, 0xd0 },22 { 0x24, 0x20 },23 { 0x57, 0x11 },24 { 0x05, 0xc8 },25};26 27static void adv7511_dsi_config_timing_gen(struct adv7511 *adv)28{29 struct mipi_dsi_device *dsi = adv->dsi;30 struct drm_display_mode *mode = &adv->curr_mode;31 unsigned int hsw, hfp, hbp, vsw, vfp, vbp;32 static const u8 clock_div_by_lanes[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */33 34 hsw = mode->hsync_end - mode->hsync_start;35 hfp = mode->hsync_start - mode->hdisplay;36 hbp = mode->htotal - mode->hsync_end;37 vsw = mode->vsync_end - mode->vsync_start;38 vfp = mode->vsync_start - mode->vdisplay;39 vbp = mode->vtotal - mode->vsync_end;40 41 /* set pixel clock divider mode */42 regmap_write(adv->regmap_cec, 0x16,43 clock_div_by_lanes[dsi->lanes - 2] << 3);44 45 /* horizontal porch params */46 regmap_write(adv->regmap_cec, 0x28, mode->htotal >> 4);47 regmap_write(adv->regmap_cec, 0x29, (mode->htotal << 4) & 0xff);48 regmap_write(adv->regmap_cec, 0x2a, hsw >> 4);49 regmap_write(adv->regmap_cec, 0x2b, (hsw << 4) & 0xff);50 regmap_write(adv->regmap_cec, 0x2c, hfp >> 4);51 regmap_write(adv->regmap_cec, 0x2d, (hfp << 4) & 0xff);52 regmap_write(adv->regmap_cec, 0x2e, hbp >> 4);53 regmap_write(adv->regmap_cec, 0x2f, (hbp << 4) & 0xff);54 55 /* vertical porch params */56 regmap_write(adv->regmap_cec, 0x30, mode->vtotal >> 4);57 regmap_write(adv->regmap_cec, 0x31, (mode->vtotal << 4) & 0xff);58 regmap_write(adv->regmap_cec, 0x32, vsw >> 4);59 regmap_write(adv->regmap_cec, 0x33, (vsw << 4) & 0xff);60 regmap_write(adv->regmap_cec, 0x34, vfp >> 4);61 regmap_write(adv->regmap_cec, 0x35, (vfp << 4) & 0xff);62 regmap_write(adv->regmap_cec, 0x36, vbp >> 4);63 regmap_write(adv->regmap_cec, 0x37, (vbp << 4) & 0xff);64}65 66void adv7533_dsi_power_on(struct adv7511 *adv)67{68 struct mipi_dsi_device *dsi = adv->dsi;69 70 if (adv->use_timing_gen)71 adv7511_dsi_config_timing_gen(adv);72 73 /* set number of dsi lanes */74 regmap_write(adv->regmap_cec, 0x1c, dsi->lanes << 4);75 76 if (adv->use_timing_gen) {77 /* reset internal timing generator */78 regmap_write(adv->regmap_cec, 0x27, 0xcb);79 regmap_write(adv->regmap_cec, 0x27, 0x8b);80 regmap_write(adv->regmap_cec, 0x27, 0xcb);81 } else {82 /* disable internal timing generator */83 regmap_write(adv->regmap_cec, 0x27, 0x0b);84 }85 86 /* enable hdmi */87 regmap_write(adv->regmap_cec, 0x03, 0x89);88 /* disable test mode */89 regmap_write(adv->regmap_cec, 0x55, 0x00);90 91 regmap_register_patch(adv->regmap_cec, adv7533_cec_fixed_registers,92 ARRAY_SIZE(adv7533_cec_fixed_registers));93}94 95void adv7533_dsi_power_off(struct adv7511 *adv)96{97 /* disable hdmi */98 regmap_write(adv->regmap_cec, 0x03, 0x0b);99 /* disable internal timing generator */100 regmap_write(adv->regmap_cec, 0x27, 0x0b);101}102 103enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv,104 const struct drm_display_mode *mode)105{106 struct mipi_dsi_device *dsi = adv->dsi;107 u8 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);108 109 /* Check max clock for either 7533 or 7535 */110 if (mode->clock > adv->info->max_mode_clock_khz)111 return MODE_CLOCK_HIGH;112 113 /* Check max clock for each lane */114 if (mode->clock * bpp > adv->info->max_lane_freq_khz * adv->num_dsi_lanes)115 return MODE_CLOCK_HIGH;116 117 return MODE_OK;118}119 120int adv7533_patch_registers(struct adv7511 *adv)121{122 return regmap_register_patch(adv->regmap,123 adv7533_fixed_registers,124 ARRAY_SIZE(adv7533_fixed_registers));125}126 127int adv7533_patch_cec_registers(struct adv7511 *adv)128{129 return regmap_register_patch(adv->regmap_cec,130 adv7533_cec_fixed_registers,131 ARRAY_SIZE(adv7533_cec_fixed_registers));132}133 134int adv7533_attach_dsi(struct adv7511 *adv)135{136 struct device *dev = &adv->i2c_main->dev;137 struct mipi_dsi_host *host;138 struct mipi_dsi_device *dsi;139 int ret = 0;140 const struct mipi_dsi_device_info info = { .type = "adv7533",141 .channel = 0,142 .node = NULL,143 };144 145 host = of_find_mipi_dsi_host_by_node(adv->host_node);146 if (!host)147 return dev_err_probe(dev, -EPROBE_DEFER,148 "failed to find dsi host\n");149 150 dsi = devm_mipi_dsi_device_register_full(dev, host, &info);151 if (IS_ERR(dsi))152 return dev_err_probe(dev, PTR_ERR(dsi),153 "failed to create dsi device\n");154 155 adv->dsi = dsi;156 157 dsi->lanes = adv->num_dsi_lanes;158 dsi->format = MIPI_DSI_FMT_RGB888;159 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |160 MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;161 162 ret = devm_mipi_dsi_attach(dev, dsi);163 if (ret < 0)164 return dev_err_probe(dev, ret, "failed to attach dsi to host\n");165 166 return 0;167}168 169int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)170{171 u32 num_lanes;172 173 of_property_read_u32(np, "adi,dsi-lanes", &num_lanes);174 175 if (num_lanes < 1 || num_lanes > 4)176 return -EINVAL;177 178 adv->num_dsi_lanes = num_lanes;179 180 adv->host_node = of_graph_get_remote_node(np, 0, 0);181 if (!adv->host_node)182 return -ENODEV;183 184 of_node_put(adv->host_node);185 186 adv->use_timing_gen = !of_property_read_bool(np,187 "adi,disable-timing-generator");188 189 /* TODO: Check if these need to be parsed by DT or not */190 adv->rgb = true;191 adv->embedded_sync = false;192 193 return 0;194}195