LCOV - code coverage report
Current view: top level - dev/pci/drm/i915 - intel_dsi_panel_vbt.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 229 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 12 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright © 2014 Intel Corporation
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice (including the next
      12             :  * paragraph) shall be included in all copies or substantial portions of the
      13             :  * Software.
      14             :  *
      15             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      20             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      21             :  * DEALINGS IN THE SOFTWARE.
      22             :  *
      23             :  * Author: Shobhit Kumar <shobhit.kumar@intel.com>
      24             :  *
      25             :  */
      26             : 
      27             : #include <dev/pci/drm/drmP.h>
      28             : #include <dev/pci/drm/drm_crtc.h>
      29             : #include <dev/pci/drm/drm_edid.h>
      30             : #include <dev/pci/drm/i915_drm.h>
      31             : #include <dev/pci/drm/drm_panel.h>
      32             : #ifdef __linux__
      33             : #include <linux/slab.h>
      34             : #include <video/mipi_display.h>
      35             : #include <asm/intel-mid.h>
      36             : #include <video/mipi_display.h>
      37             : #endif
      38             : #include "i915_drv.h"
      39             : #include "intel_drv.h"
      40             : #include "intel_dsi.h"
      41             : 
      42             : struct vbt_panel {
      43             :         struct drm_panel panel;
      44             :         struct intel_dsi *intel_dsi;
      45             : };
      46             : 
      47           0 : static inline struct vbt_panel *to_vbt_panel(struct drm_panel *panel)
      48             : {
      49           0 :         return container_of(panel, struct vbt_panel, panel);
      50             : }
      51             : 
      52             : #define MIPI_TRANSFER_MODE_SHIFT        0
      53             : #define MIPI_VIRTUAL_CHANNEL_SHIFT      1
      54             : #define MIPI_PORT_SHIFT                 3
      55             : 
      56             : #define PREPARE_CNT_MAX         0x3F
      57             : #define EXIT_ZERO_CNT_MAX       0x3F
      58             : #define CLK_ZERO_CNT_MAX        0xFF
      59             : #define TRAIL_CNT_MAX           0x1F
      60             : 
      61             : #define NS_KHZ_RATIO 1000000
      62             : 
      63             : #define GPI0_NC_0_HV_DDI0_HPD           0x4130
      64             : #define GPIO_NC_0_HV_DDI0_PAD           0x4138
      65             : #define GPIO_NC_1_HV_DDI0_DDC_SDA       0x4120
      66             : #define GPIO_NC_1_HV_DDI0_DDC_SDA_PAD   0x4128
      67             : #define GPIO_NC_2_HV_DDI0_DDC_SCL       0x4110
      68             : #define GPIO_NC_2_HV_DDI0_DDC_SCL_PAD   0x4118
      69             : #define GPIO_NC_3_PANEL0_VDDEN          0x4140
      70             : #define GPIO_NC_3_PANEL0_VDDEN_PAD      0x4148
      71             : #define GPIO_NC_4_PANEL0_BLKEN          0x4150
      72             : #define GPIO_NC_4_PANEL0_BLKEN_PAD      0x4158
      73             : #define GPIO_NC_5_PANEL0_BLKCTL         0x4160
      74             : #define GPIO_NC_5_PANEL0_BLKCTL_PAD     0x4168
      75             : #define GPIO_NC_6_PCONF0                0x4180
      76             : #define GPIO_NC_6_PAD                   0x4188
      77             : #define GPIO_NC_7_PCONF0                0x4190
      78             : #define GPIO_NC_7_PAD                   0x4198
      79             : #define GPIO_NC_8_PCONF0                0x4170
      80             : #define GPIO_NC_8_PAD                   0x4178
      81             : #define GPIO_NC_9_PCONF0                0x4100
      82             : #define GPIO_NC_9_PAD                   0x4108
      83             : #define GPIO_NC_10_PCONF0               0x40E0
      84             : #define GPIO_NC_10_PAD                  0x40E8
      85             : #define GPIO_NC_11_PCONF0               0x40F0
      86             : #define GPIO_NC_11_PAD                  0x40F8
      87             : 
      88             : struct gpio_table {
      89             :         u16 function_reg;
      90             :         u16 pad_reg;
      91             :         u8 init;
      92             : };
      93             : 
      94             : static struct gpio_table gtable[] = {
      95             :         { GPI0_NC_0_HV_DDI0_HPD, GPIO_NC_0_HV_DDI0_PAD, 0 },
      96             :         { GPIO_NC_1_HV_DDI0_DDC_SDA, GPIO_NC_1_HV_DDI0_DDC_SDA_PAD, 0 },
      97             :         { GPIO_NC_2_HV_DDI0_DDC_SCL, GPIO_NC_2_HV_DDI0_DDC_SCL_PAD, 0 },
      98             :         { GPIO_NC_3_PANEL0_VDDEN, GPIO_NC_3_PANEL0_VDDEN_PAD, 0 },
      99             :         { GPIO_NC_4_PANEL0_BLKEN, GPIO_NC_4_PANEL0_BLKEN_PAD, 0 },
     100             :         { GPIO_NC_5_PANEL0_BLKCTL, GPIO_NC_5_PANEL0_BLKCTL_PAD, 0 },
     101             :         { GPIO_NC_6_PCONF0, GPIO_NC_6_PAD, 0 },
     102             :         { GPIO_NC_7_PCONF0, GPIO_NC_7_PAD, 0 },
     103             :         { GPIO_NC_8_PCONF0, GPIO_NC_8_PAD, 0 },
     104             :         { GPIO_NC_9_PCONF0, GPIO_NC_9_PAD, 0 },
     105             :         { GPIO_NC_10_PCONF0, GPIO_NC_10_PAD, 0},
     106             :         { GPIO_NC_11_PCONF0, GPIO_NC_11_PAD, 0}
     107             : };
     108             : 
     109           0 : static inline enum port intel_dsi_seq_port_to_port(u8 port)
     110             : {
     111           0 :         return port ? PORT_C : PORT_A;
     112             : }
     113             : 
     114           0 : static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi,
     115             :                                        const u8 *data)
     116             : {
     117             :         struct mipi_dsi_device *dsi_device;
     118             :         u8 type, flags, seq_port;
     119             :         u16 len;
     120             :         enum port port;
     121             : 
     122           0 :         flags = *data++;
     123           0 :         type = *data++;
     124             : 
     125           0 :         len = *((u16 *) data);
     126           0 :         data += 2;
     127             : 
     128           0 :         seq_port = (flags >> MIPI_PORT_SHIFT) & 3;
     129             : 
     130             :         /* For DSI single link on Port A & C, the seq_port value which is
     131             :          * parsed from Sequence Block#53 of VBT has been set to 0
     132             :          * Now, read/write of packets for the DSI single link on Port A and
     133             :          * Port C will based on the DVO port from VBT block 2.
     134             :          */
     135           0 :         if (intel_dsi->ports == (1 << PORT_C))
     136           0 :                 port = PORT_C;
     137             :         else
     138           0 :                 port = intel_dsi_seq_port_to_port(seq_port);
     139             : 
     140           0 :         dsi_device = intel_dsi->dsi_hosts[port]->device;
     141           0 :         if (!dsi_device) {
     142             :                 DRM_DEBUG_KMS("no dsi device for port %c\n", port_name(port));
     143             :                 goto out;
     144             :         }
     145             : 
     146           0 :         if ((flags >> MIPI_TRANSFER_MODE_SHIFT) & 1)
     147           0 :                 dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM;
     148             :         else
     149           0 :                 dsi_device->mode_flags |= MIPI_DSI_MODE_LPM;
     150             : 
     151           0 :         dsi_device->channel = (flags >> MIPI_VIRTUAL_CHANNEL_SHIFT) & 3;
     152             : 
     153           0 :         switch (type) {
     154             :         case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
     155           0 :                 mipi_dsi_generic_write(dsi_device, NULL, 0);
     156           0 :                 break;
     157             :         case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
     158           0 :                 mipi_dsi_generic_write(dsi_device, data, 1);
     159           0 :                 break;
     160             :         case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
     161           0 :                 mipi_dsi_generic_write(dsi_device, data, 2);
     162           0 :                 break;
     163             :         case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
     164             :         case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
     165             :         case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
     166             :                 DRM_DEBUG_DRIVER("Generic Read not yet implemented or used\n");
     167             :                 break;
     168             :         case MIPI_DSI_GENERIC_LONG_WRITE:
     169           0 :                 mipi_dsi_generic_write(dsi_device, data, len);
     170           0 :                 break;
     171             :         case MIPI_DSI_DCS_SHORT_WRITE:
     172           0 :                 mipi_dsi_dcs_write_buffer(dsi_device, data, 1);
     173           0 :                 break;
     174             :         case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
     175           0 :                 mipi_dsi_dcs_write_buffer(dsi_device, data, 2);
     176           0 :                 break;
     177             :         case MIPI_DSI_DCS_READ:
     178             :                 DRM_DEBUG_DRIVER("DCS Read not yet implemented or used\n");
     179             :                 break;
     180             :         case MIPI_DSI_DCS_LONG_WRITE:
     181           0 :                 mipi_dsi_dcs_write_buffer(dsi_device, data, len);
     182           0 :                 break;
     183             :         }
     184             : 
     185             : out:
     186           0 :         data += len;
     187             : 
     188           0 :         return data;
     189             : }
     190             : 
     191           0 : static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data)
     192             : {
     193           0 :         u32 delay = *((const u32 *) data);
     194             : 
     195           0 :         usleep_range(delay, delay + 10);
     196           0 :         data += 4;
     197             : 
     198           0 :         return data;
     199             : }
     200             : 
     201           0 : static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
     202             : {
     203             :         u8 gpio, action;
     204             :         u16 function, pad;
     205             :         u32 val;
     206           0 :         struct drm_device *dev = intel_dsi->base.base.dev;
     207           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     208             : 
     209           0 :         gpio = *data++;
     210             : 
     211             :         /* pull up/down */
     212           0 :         action = *data++ & 1;
     213             : 
     214           0 :         if (gpio >= ARRAY_SIZE(gtable)) {
     215             :                 DRM_DEBUG_KMS("unknown gpio %u\n", gpio);
     216             :                 goto out;
     217             :         }
     218             : 
     219           0 :         function = gtable[gpio].function_reg;
     220           0 :         pad = gtable[gpio].pad_reg;
     221             : 
     222           0 :         mutex_lock(&dev_priv->sb_lock);
     223           0 :         if (!gtable[gpio].init) {
     224             :                 /* program the function */
     225             :                 /* FIXME: remove constant below */
     226           0 :                 vlv_gpio_nc_write(dev_priv, function, 0x2000CC00);
     227           0 :                 gtable[gpio].init = 1;
     228           0 :         }
     229             : 
     230           0 :         val = 0x4 | action;
     231             : 
     232             :         /* pull up/down */
     233           0 :         vlv_gpio_nc_write(dev_priv, pad, val);
     234           0 :         mutex_unlock(&dev_priv->sb_lock);
     235             : 
     236             : out:
     237           0 :         return data;
     238             : }
     239             : 
     240             : typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi,
     241             :                                         const u8 *data);
     242             : static const fn_mipi_elem_exec exec_elem[] = {
     243             :         NULL, /* reserved */
     244             :         mipi_exec_send_packet,
     245             :         mipi_exec_delay,
     246             :         mipi_exec_gpio,
     247             :         NULL, /* status read; later */
     248             : };
     249             : 
     250             : /*
     251             :  * MIPI Sequence from VBT #53 parsing logic
     252             :  * We have already separated each seqence during bios parsing
     253             :  * Following is generic execution function for any sequence
     254             :  */
     255             : 
     256             : static const char * const seq_name[] = {
     257             :         "UNDEFINED",
     258             :         "MIPI_SEQ_ASSERT_RESET",
     259             :         "MIPI_SEQ_INIT_OTP",
     260             :         "MIPI_SEQ_DISPLAY_ON",
     261             :         "MIPI_SEQ_DISPLAY_OFF",
     262             :         "MIPI_SEQ_DEASSERT_RESET"
     263             : };
     264             : 
     265           0 : static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data)
     266             : {
     267             :         fn_mipi_elem_exec mipi_elem_exec;
     268             :         int index;
     269             : 
     270           0 :         if (!data)
     271           0 :                 return;
     272             : 
     273             :         DRM_DEBUG_DRIVER("Starting MIPI sequence - %s\n", seq_name[*data]);
     274             : 
     275             :         /* go to the first element of the sequence */
     276           0 :         data++;
     277             : 
     278             :         /* parse each byte till we reach end of sequence byte - 0x00 */
     279           0 :         while (1) {
     280           0 :                 index = *data;
     281           0 :                 mipi_elem_exec = exec_elem[index];
     282           0 :                 if (!mipi_elem_exec) {
     283           0 :                         DRM_ERROR("Unsupported MIPI element, skipping sequence execution\n");
     284           0 :                         return;
     285             :                 }
     286             : 
     287             :                 /* goto element payload */
     288           0 :                 data++;
     289             : 
     290             :                 /* execute the element specific rotines */
     291           0 :                 data = mipi_elem_exec(intel_dsi, data);
     292             : 
     293             :                 /*
     294             :                  * After processing the element, data should point to
     295             :                  * next element or end of sequence
     296             :                  * check if have we reached end of sequence
     297             :                  */
     298           0 :                 if (*data == 0x00)
     299             :                         break;
     300             :         }
     301           0 : }
     302             : 
     303           0 : static int vbt_panel_prepare(struct drm_panel *panel)
     304             : {
     305           0 :         struct vbt_panel *vbt_panel = to_vbt_panel(panel);
     306           0 :         struct intel_dsi *intel_dsi = vbt_panel->intel_dsi;
     307           0 :         struct drm_device *dev = intel_dsi->base.base.dev;
     308           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     309             :         const u8 *sequence;
     310             : 
     311           0 :         sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET];
     312           0 :         generic_exec_sequence(intel_dsi, sequence);
     313             : 
     314           0 :         sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
     315           0 :         generic_exec_sequence(intel_dsi, sequence);
     316             : 
     317           0 :         return 0;
     318             : }
     319             : 
     320           0 : static int vbt_panel_unprepare(struct drm_panel *panel)
     321             : {
     322           0 :         struct vbt_panel *vbt_panel = to_vbt_panel(panel);
     323           0 :         struct intel_dsi *intel_dsi = vbt_panel->intel_dsi;
     324           0 :         struct drm_device *dev = intel_dsi->base.base.dev;
     325           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     326             :         const u8 *sequence;
     327             : 
     328           0 :         sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET];
     329           0 :         generic_exec_sequence(intel_dsi, sequence);
     330             : 
     331           0 :         return 0;
     332             : }
     333             : 
     334           0 : static int vbt_panel_enable(struct drm_panel *panel)
     335             : {
     336           0 :         struct vbt_panel *vbt_panel = to_vbt_panel(panel);
     337           0 :         struct intel_dsi *intel_dsi = vbt_panel->intel_dsi;
     338           0 :         struct drm_device *dev = intel_dsi->base.base.dev;
     339           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     340             :         const u8 *sequence;
     341             : 
     342           0 :         sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_ON];
     343           0 :         generic_exec_sequence(intel_dsi, sequence);
     344             : 
     345           0 :         return 0;
     346             : }
     347             : 
     348           0 : static int vbt_panel_disable(struct drm_panel *panel)
     349             : {
     350           0 :         struct vbt_panel *vbt_panel = to_vbt_panel(panel);
     351           0 :         struct intel_dsi *intel_dsi = vbt_panel->intel_dsi;
     352           0 :         struct drm_device *dev = intel_dsi->base.base.dev;
     353           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     354             :         const u8 *sequence;
     355             : 
     356           0 :         sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_OFF];
     357           0 :         generic_exec_sequence(intel_dsi, sequence);
     358             : 
     359           0 :         return 0;
     360             : }
     361             : 
     362           0 : static int vbt_panel_get_modes(struct drm_panel *panel)
     363             : {
     364           0 :         struct vbt_panel *vbt_panel = to_vbt_panel(panel);
     365           0 :         struct intel_dsi *intel_dsi = vbt_panel->intel_dsi;
     366           0 :         struct drm_device *dev = intel_dsi->base.base.dev;
     367           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     368             :         struct drm_display_mode *mode;
     369             : 
     370           0 :         if (!panel->connector)
     371           0 :                 return 0;
     372             : 
     373           0 :         mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode);
     374           0 :         if (!mode)
     375           0 :                 return 0;
     376             : 
     377           0 :         mode->type |= DRM_MODE_TYPE_PREFERRED;
     378             : 
     379           0 :         drm_mode_probed_add(panel->connector, mode);
     380             : 
     381           0 :         return 1;
     382           0 : }
     383             : 
     384             : static const struct drm_panel_funcs vbt_panel_funcs = {
     385             :         .disable = vbt_panel_disable,
     386             :         .unprepare = vbt_panel_unprepare,
     387             :         .prepare = vbt_panel_prepare,
     388             :         .enable = vbt_panel_enable,
     389             :         .get_modes = vbt_panel_get_modes,
     390             : };
     391             : 
     392           0 : struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id)
     393             : {
     394           0 :         struct drm_device *dev = intel_dsi->base.base.dev;
     395           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     396           0 :         struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
     397           0 :         struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps;
     398           0 :         struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode;
     399             :         struct vbt_panel *vbt_panel;
     400             :         u32 bits_per_pixel = 24;
     401             :         u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui;
     402             :         u32 ui_num, ui_den;
     403             :         u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
     404             :         u32 ths_prepare_ns, tclk_trail_ns;
     405             :         u32 tclk_prepare_clkzero, ths_prepare_hszero;
     406             :         u32 lp_to_hs_switch, hs_to_lp_switch;
     407             :         u32 pclk, computed_ddr;
     408             :         u16 burst_mode_ratio;
     409             :         enum port port;
     410             : 
     411             :         DRM_DEBUG_KMS("\n");
     412             : 
     413           0 :         intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1;
     414           0 :         intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
     415           0 :         intel_dsi->lane_count = mipi_config->lane_cnt + 1;
     416           0 :         intel_dsi->pixel_format = mipi_config->videomode_color_format << 7;
     417           0 :         intel_dsi->dual_link = mipi_config->dual_link;
     418           0 :         intel_dsi->pixel_overlap = mipi_config->pixel_overlap;
     419             : 
     420           0 :         if (intel_dsi->pixel_format == VID_MODE_FORMAT_RGB666)
     421           0 :                 bits_per_pixel = 18;
     422           0 :         else if (intel_dsi->pixel_format == VID_MODE_FORMAT_RGB565)
     423           0 :                 bits_per_pixel = 16;
     424             : 
     425           0 :         intel_dsi->operation_mode = mipi_config->is_cmd_mode;
     426           0 :         intel_dsi->video_mode_format = mipi_config->video_transfer_mode;
     427           0 :         intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
     428           0 :         intel_dsi->lp_rx_timeout = mipi_config->lp_rx_timeout;
     429           0 :         intel_dsi->turn_arnd_val = mipi_config->turn_around_timeout;
     430           0 :         intel_dsi->rst_timer_val = mipi_config->device_reset_timer;
     431           0 :         intel_dsi->init_count = mipi_config->master_init_timer;
     432           0 :         intel_dsi->bw_timer = mipi_config->dbi_bw_timer;
     433           0 :         intel_dsi->video_frmt_cfg_bits =
     434           0 :                 mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
     435             : 
     436           0 :         pclk = mode->clock;
     437             : 
     438             :         /* In dual link mode each port needs half of pixel clock */
     439           0 :         if (intel_dsi->dual_link) {
     440           0 :                 pclk = pclk / 2;
     441             : 
     442             :                 /* we can enable pixel_overlap if needed by panel. In this
     443             :                  * case we need to increase the pixelclock for extra pixels
     444             :                  */
     445           0 :                 if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
     446           0 :                         pclk += DIV_ROUND_UP(mode->vtotal *
     447             :                                                 intel_dsi->pixel_overlap *
     448             :                                                 60, 1000);
     449           0 :                 }
     450             :         }
     451             : 
     452             :         /* Burst Mode Ratio
     453             :          * Target ddr frequency from VBT / non burst ddr freq
     454             :          * multiply by 100 to preserve remainder
     455             :          */
     456           0 :         if (intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
     457           0 :                 if (mipi_config->target_burst_mode_freq) {
     458             :                         computed_ddr =
     459           0 :                                 (pclk * bits_per_pixel) / intel_dsi->lane_count;
     460             : 
     461           0 :                         if (mipi_config->target_burst_mode_freq <
     462             :                                                                 computed_ddr) {
     463           0 :                                 DRM_ERROR("Burst mode freq is less than computed\n");
     464           0 :                                 return NULL;
     465             :                         }
     466             : 
     467           0 :                         burst_mode_ratio = DIV_ROUND_UP(
     468             :                                 mipi_config->target_burst_mode_freq * 100,
     469             :                                 computed_ddr);
     470             : 
     471           0 :                         pclk = DIV_ROUND_UP(pclk * burst_mode_ratio, 100);
     472             :                 } else {
     473           0 :                         DRM_ERROR("Burst mode target is not set\n");
     474           0 :                         return NULL;
     475             :                 }
     476           0 :         } else
     477             :                 burst_mode_ratio = 100;
     478             : 
     479           0 :         intel_dsi->burst_mode_ratio = burst_mode_ratio;
     480           0 :         intel_dsi->pclk = pclk;
     481             : 
     482           0 :         bitrate = (pclk * bits_per_pixel) / intel_dsi->lane_count;
     483             : 
     484           0 :         switch (intel_dsi->escape_clk_div) {
     485             :         case 0:
     486             :                 tlpx_ns = 50;
     487           0 :                 break;
     488             :         case 1:
     489             :                 tlpx_ns = 100;
     490           0 :                 break;
     491             : 
     492             :         case 2:
     493             :                 tlpx_ns = 200;
     494           0 :                 break;
     495             :         default:
     496             :                 tlpx_ns = 50;
     497           0 :                 break;
     498             :         }
     499             : 
     500           0 :         switch (intel_dsi->lane_count) {
     501             :         case 1:
     502             :         case 2:
     503             :                 extra_byte_count = 2;
     504           0 :                 break;
     505             :         case 3:
     506             :                 extra_byte_count = 4;
     507           0 :                 break;
     508             :         case 4:
     509             :         default:
     510             :                 extra_byte_count = 3;
     511           0 :                 break;
     512             :         }
     513             : 
     514             :         /*
     515             :          * ui(s) = 1/f [f in hz]
     516             :          * ui(ns) = 10^9 / (f*10^6) [f in Mhz] -> 10^3/f(Mhz)
     517             :          */
     518             : 
     519             :         /* in Kbps */
     520             :         ui_num = NS_KHZ_RATIO;
     521             :         ui_den = bitrate;
     522             : 
     523           0 :         tclk_prepare_clkzero = mipi_config->tclk_prepare_clkzero;
     524           0 :         ths_prepare_hszero = mipi_config->ths_prepare_hszero;
     525             : 
     526             :         /*
     527             :          * B060
     528             :          * LP byte clock = TLPX/ (8UI)
     529             :          */
     530           0 :         intel_dsi->lp_byte_clk = DIV_ROUND_UP(tlpx_ns * ui_den, 8 * ui_num);
     531             : 
     532             :         /* count values in UI = (ns value) * (bitrate / (2 * 10^6))
     533             :          *
     534             :          * Since txddrclkhs_i is 2xUI, all the count values programmed in
     535             :          * DPHY param register are divided by 2
     536             :          *
     537             :          * prepare count
     538             :          */
     539           0 :         ths_prepare_ns = max(mipi_config->ths_prepare,
     540           0 :                              mipi_config->tclk_prepare);
     541           0 :         prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * 2);
     542             : 
     543             :         /* exit zero count */
     544           0 :         exit_zero_cnt = DIV_ROUND_UP(
     545             :                                 (ths_prepare_hszero - ths_prepare_ns) * ui_den,
     546             :                                 ui_num * 2
     547             :                                 );
     548             : 
     549             :         /*
     550             :          * Exit zero  is unified val ths_zero and ths_exit
     551             :          * minimum value for ths_exit = 110ns
     552             :          * min (exit_zero_cnt * 2) = 110/UI
     553             :          * exit_zero_cnt = 55/UI
     554             :          */
     555           0 :          if (exit_zero_cnt < (55 * ui_den / ui_num))
     556           0 :                 if ((55 * ui_den) % ui_num)
     557           0 :                         exit_zero_cnt += 1;
     558             : 
     559             :         /* clk zero count */
     560           0 :         clk_zero_cnt = DIV_ROUND_UP(
     561             :                         (tclk_prepare_clkzero - ths_prepare_ns)
     562             :                         * ui_den, 2 * ui_num);
     563             : 
     564             :         /* trail count */
     565           0 :         tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
     566           0 :         trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, 2 * ui_num);
     567             : 
     568           0 :         if (prepare_cnt > PREPARE_CNT_MAX ||
     569           0 :                 exit_zero_cnt > EXIT_ZERO_CNT_MAX ||
     570           0 :                 clk_zero_cnt > CLK_ZERO_CNT_MAX ||
     571           0 :                 trail_cnt > TRAIL_CNT_MAX)
     572             :                 DRM_DEBUG_DRIVER("Values crossing maximum limits, restricting to max values\n");
     573             : 
     574           0 :         if (prepare_cnt > PREPARE_CNT_MAX)
     575           0 :                 prepare_cnt = PREPARE_CNT_MAX;
     576             : 
     577           0 :         if (exit_zero_cnt > EXIT_ZERO_CNT_MAX)
     578           0 :                 exit_zero_cnt = EXIT_ZERO_CNT_MAX;
     579             : 
     580           0 :         if (clk_zero_cnt > CLK_ZERO_CNT_MAX)
     581           0 :                 clk_zero_cnt = CLK_ZERO_CNT_MAX;
     582             : 
     583           0 :         if (trail_cnt > TRAIL_CNT_MAX)
     584           0 :                 trail_cnt = TRAIL_CNT_MAX;
     585             : 
     586             :         /* B080 */
     587           0 :         intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
     588           0 :                                                 clk_zero_cnt << 8 | prepare_cnt;
     589             : 
     590             :         /*
     591             :          * LP to HS switch count = 4TLPX + PREP_COUNT * 2 + EXIT_ZERO_COUNT * 2
     592             :          *                                      + 10UI + Extra Byte Count
     593             :          *
     594             :          * HS to LP switch count = THS-TRAIL + 2TLPX + Extra Byte Count
     595             :          * Extra Byte Count is calculated according to number of lanes.
     596             :          * High Low Switch Count is the Max of LP to HS and
     597             :          * HS to LP switch count
     598             :          *
     599             :          */
     600           0 :         tlpx_ui = DIV_ROUND_UP(tlpx_ns * ui_den, ui_num);
     601             : 
     602             :         /* B044 */
     603             :         /* FIXME:
     604             :          * The comment above does not match with the code */
     605           0 :         lp_to_hs_switch = DIV_ROUND_UP(4 * tlpx_ui + prepare_cnt * 2 +
     606             :                                                 exit_zero_cnt * 2 + 10, 8);
     607             : 
     608           0 :         hs_to_lp_switch = DIV_ROUND_UP(mipi_config->ths_trail + 2 * tlpx_ui, 8);
     609             : 
     610           0 :         intel_dsi->hs_to_lp_count = max(lp_to_hs_switch, hs_to_lp_switch);
     611           0 :         intel_dsi->hs_to_lp_count += extra_byte_count;
     612             : 
     613             :         /* B088 */
     614             :         /* LP -> HS for clock lanes
     615             :          * LP clk sync + LP11 + LP01 + tclk_prepare + tclk_zero +
     616             :          *                                              extra byte count
     617             :          * 2TPLX + 1TLPX + 1 TPLX(in ns) + prepare_cnt * 2 + clk_zero_cnt *
     618             :          *                                      2(in UI) + extra byte count
     619             :          * In byteclks = (4TLPX + prepare_cnt * 2 + clk_zero_cnt *2 (in UI)) /
     620             :          *                                      8 + extra byte count
     621             :          */
     622           0 :         intel_dsi->clk_lp_to_hs_count =
     623           0 :                 DIV_ROUND_UP(
     624             :                         4 * tlpx_ui + prepare_cnt * 2 +
     625             :                         clk_zero_cnt * 2,
     626             :                         8);
     627             : 
     628           0 :         intel_dsi->clk_lp_to_hs_count += extra_byte_count;
     629             : 
     630             :         /* HS->LP for Clock Lanes
     631             :          * Low Power clock synchronisations + 1Tx byteclk + tclk_trail +
     632             :          *                                              Extra byte count
     633             :          * 2TLPX + 8UI + (trail_count*2)(in UI) + Extra byte count
     634             :          * In byteclks = (2*TLpx(in UI) + trail_count*2 +8)(in UI)/8 +
     635             :          *                                              Extra byte count
     636             :          */
     637           0 :         intel_dsi->clk_hs_to_lp_count =
     638           0 :                 DIV_ROUND_UP(2 * tlpx_ui + trail_cnt * 2 + 8,
     639             :                         8);
     640           0 :         intel_dsi->clk_hs_to_lp_count += extra_byte_count;
     641             : 
     642             :         DRM_DEBUG_KMS("Eot %s\n", intel_dsi->eotp_pkt ? "enabled" : "disabled");
     643             :         DRM_DEBUG_KMS("Clockstop %s\n", intel_dsi->clock_stop ?
     644             :                                                 "disabled" : "enabled");
     645             :         DRM_DEBUG_KMS("Mode %s\n", intel_dsi->operation_mode ? "command" : "video");
     646           0 :         if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
     647             :                 DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_FRONT_BACK\n");
     648             :         else if (intel_dsi->dual_link == DSI_DUAL_LINK_PIXEL_ALT)
     649             :                 DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_PIXEL_ALT\n");
     650             :         else
     651             :                 DRM_DEBUG_KMS("Dual link: NONE\n");
     652             :         DRM_DEBUG_KMS("Pixel Format %d\n", intel_dsi->pixel_format);
     653             :         DRM_DEBUG_KMS("TLPX %d\n", intel_dsi->escape_clk_div);
     654             :         DRM_DEBUG_KMS("LP RX Timeout 0x%x\n", intel_dsi->lp_rx_timeout);
     655             :         DRM_DEBUG_KMS("Turnaround Timeout 0x%x\n", intel_dsi->turn_arnd_val);
     656             :         DRM_DEBUG_KMS("Init Count 0x%x\n", intel_dsi->init_count);
     657             :         DRM_DEBUG_KMS("HS to LP Count 0x%x\n", intel_dsi->hs_to_lp_count);
     658             :         DRM_DEBUG_KMS("LP Byte Clock %d\n", intel_dsi->lp_byte_clk);
     659             :         DRM_DEBUG_KMS("DBI BW Timer 0x%x\n", intel_dsi->bw_timer);
     660             :         DRM_DEBUG_KMS("LP to HS Clock Count 0x%x\n", intel_dsi->clk_lp_to_hs_count);
     661             :         DRM_DEBUG_KMS("HS to LP Clock Count 0x%x\n", intel_dsi->clk_hs_to_lp_count);
     662             :         DRM_DEBUG_KMS("BTA %s\n",
     663             :                         intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA ?
     664             :                         "disabled" : "enabled");
     665             : 
     666             :         /* delays in VBT are in unit of 100us, so need to convert
     667             :          * here in ms
     668             :          * Delay (100us) * 100 /1000 = Delay / 10 (ms) */
     669           0 :         intel_dsi->backlight_off_delay = pps->bl_disable_delay / 10;
     670           0 :         intel_dsi->backlight_on_delay = pps->bl_enable_delay / 10;
     671           0 :         intel_dsi->panel_on_delay = pps->panel_on_delay / 10;
     672           0 :         intel_dsi->panel_off_delay = pps->panel_off_delay / 10;
     673           0 :         intel_dsi->panel_pwr_cycle_delay = pps->panel_power_cycle_delay / 10;
     674             : 
     675             :         /* This is cheating a bit with the cleanup. */
     676           0 :         vbt_panel = devm_kzalloc(dev->dev, sizeof(*vbt_panel), GFP_KERNEL);
     677             : 
     678           0 :         vbt_panel->intel_dsi = intel_dsi;
     679           0 :         drm_panel_init(&vbt_panel->panel);
     680           0 :         vbt_panel->panel.funcs = &vbt_panel_funcs;
     681           0 :         drm_panel_add(&vbt_panel->panel);
     682             : 
     683             :         /* a regular driver would get the device in probe */
     684           0 :         for_each_dsi_port(port, intel_dsi->ports) {
     685           0 :                 mipi_dsi_attach(intel_dsi->dsi_hosts[port]->device);
     686           0 :         }
     687             : 
     688           0 :         return &vbt_panel->panel;
     689           0 : }

Generated by: LCOV version 1.13