2013-08-27 15:12:20 +03:00
/*
* Copyright © 2013 Intel Corporation
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the next
* paragraph ) shall be included in all copies or substantial portions of the
* Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
*
* Author : Jani Nikula < jani . nikula @ intel . com >
*/
# include <drm/drmP.h>
2015-01-22 16:50:32 -08:00
# include <drm/drm_atomic_helper.h>
2013-08-27 15:12:20 +03:00
# include <drm/drm_crtc.h>
# include <drm/drm_edid.h>
# include <drm/i915_drm.h>
2015-01-23 15:30:56 +02:00
# include <drm/drm_panel.h>
2015-01-16 14:27:23 +02:00
# include <drm/drm_mipi_dsi.h>
2013-08-27 15:12:20 +03:00
# include <linux/slab.h>
# include "i915_drv.h"
# include "intel_drv.h"
# include "intel_dsi.h"
2015-01-23 15:30:56 +02:00
static const struct {
u16 panel_id ;
struct drm_panel * ( * init ) ( struct intel_dsi * intel_dsi , u16 panel_id ) ;
} intel_dsi_drivers [ ] = {
2014-05-23 21:35:27 +05:30
{
. panel_id = MIPI_DSI_GENERIC_PANEL_ID ,
2015-01-23 15:30:56 +02:00
. init = vbt_panel_init ,
2014-05-23 21:35:27 +05:30
} ,
2013-08-27 15:12:20 +03:00
} ;
2015-01-16 14:27:19 +02:00
static void wait_for_dsi_fifo_empty ( struct intel_dsi * intel_dsi , enum port port )
2015-01-16 14:27:18 +02:00
{
struct drm_encoder * encoder = & intel_dsi - > base . base ;
struct drm_device * dev = encoder - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
u32 mask ;
mask = LP_CTRL_FIFO_EMPTY | HS_CTRL_FIFO_EMPTY |
LP_DATA_FIFO_EMPTY | HS_DATA_FIFO_EMPTY ;
if ( wait_for ( ( I915_READ ( MIPI_GEN_FIFO_STAT ( port ) ) & mask ) = = mask , 100 ) )
DRM_ERROR ( " DPI FIFOs are not empty \n " ) ;
}
2015-01-16 14:27:23 +02:00
static void write_data ( struct drm_i915_private * dev_priv , u32 reg ,
const u8 * data , u32 len )
{
u32 i , j ;
for ( i = 0 ; i < len ; i + = 4 ) {
u32 val = 0 ;
for ( j = 0 ; j < min_t ( u32 , len - i , 4 ) ; j + + )
val | = * data + + < < 8 * j ;
I915_WRITE ( reg , val ) ;
}
}
static void read_data ( struct drm_i915_private * dev_priv , u32 reg ,
u8 * data , u32 len )
{
u32 i , j ;
for ( i = 0 ; i < len ; i + = 4 ) {
u32 val = I915_READ ( reg ) ;
for ( j = 0 ; j < min_t ( u32 , len - i , 4 ) ; j + + )
* data + + = val > > 8 * j ;
}
}
static ssize_t intel_dsi_host_transfer ( struct mipi_dsi_host * host ,
const struct mipi_dsi_msg * msg )
{
struct intel_dsi_host * intel_dsi_host = to_intel_dsi_host ( host ) ;
struct drm_device * dev = intel_dsi_host - > intel_dsi - > base . base . dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
enum port port = intel_dsi_host - > port ;
struct mipi_dsi_packet packet ;
ssize_t ret ;
const u8 * header , * data ;
u32 data_reg , data_mask , ctrl_reg , ctrl_mask ;
ret = mipi_dsi_create_packet ( & packet , msg ) ;
if ( ret < 0 )
return ret ;
header = packet . header ;
data = packet . payload ;
if ( msg - > flags & MIPI_DSI_MSG_USE_LPM ) {
data_reg = MIPI_LP_GEN_DATA ( port ) ;
data_mask = LP_DATA_FIFO_FULL ;
ctrl_reg = MIPI_LP_GEN_CTRL ( port ) ;
ctrl_mask = LP_CTRL_FIFO_FULL ;
} else {
data_reg = MIPI_HS_GEN_DATA ( port ) ;
data_mask = HS_DATA_FIFO_FULL ;
ctrl_reg = MIPI_HS_GEN_CTRL ( port ) ;
ctrl_mask = HS_CTRL_FIFO_FULL ;
}
/* note: this is never true for reads */
if ( packet . payload_length ) {
if ( wait_for ( ( I915_READ ( MIPI_GEN_FIFO_STAT ( port ) ) & data_mask ) = = 0 , 50 ) )
DRM_ERROR ( " Timeout waiting for HS/LP DATA FIFO !full \n " ) ;
write_data ( dev_priv , data_reg , packet . payload ,
packet . payload_length ) ;
}
if ( msg - > rx_len ) {
I915_WRITE ( MIPI_INTR_STAT ( port ) , GEN_READ_DATA_AVAIL ) ;
}
if ( wait_for ( ( I915_READ ( MIPI_GEN_FIFO_STAT ( port ) ) & ctrl_mask ) = = 0 , 50 ) ) {
DRM_ERROR ( " Timeout waiting for HS/LP CTRL FIFO !full \n " ) ;
}
I915_WRITE ( ctrl_reg , header [ 2 ] < < 16 | header [ 1 ] < < 8 | header [ 0 ] ) ;
/* ->rx_len is set only for reads */
if ( msg - > rx_len ) {
data_mask = GEN_READ_DATA_AVAIL ;
if ( wait_for ( ( I915_READ ( MIPI_INTR_STAT ( port ) ) & data_mask ) = = data_mask , 50 ) )
DRM_ERROR ( " Timeout waiting for read data. \n " ) ;
read_data ( dev_priv , data_reg , msg - > rx_buf , msg - > rx_len ) ;
}
/* XXX: fix for reads and writes */
return 4 + packet . payload_length ;
}
static int intel_dsi_host_attach ( struct mipi_dsi_host * host ,
struct mipi_dsi_device * dsi )
{
return 0 ;
}
static int intel_dsi_host_detach ( struct mipi_dsi_host * host ,
struct mipi_dsi_device * dsi )
{
return 0 ;
}
static const struct mipi_dsi_host_ops intel_dsi_host_ops = {
. attach = intel_dsi_host_attach ,
. detach = intel_dsi_host_detach ,
. transfer = intel_dsi_host_transfer ,
} ;
static struct intel_dsi_host * intel_dsi_host_init ( struct intel_dsi * intel_dsi ,
enum port port )
{
struct intel_dsi_host * host ;
struct mipi_dsi_device * device ;
host = kzalloc ( sizeof ( * host ) , GFP_KERNEL ) ;
if ( ! host )
return NULL ;
host - > base . ops = & intel_dsi_host_ops ;
host - > intel_dsi = intel_dsi ;
host - > port = port ;
/*
* We should call mipi_dsi_host_register ( & host - > base ) here , but we don ' t
* have a host - > dev , and we don ' t have OF stuff either . So just use the
* dsi framework as a library and hope for the best . Create the dsi
* devices by ourselves here too . Need to be careful though , because we
* don ' t initialize any of the driver model devices here .
*/
device = kzalloc ( sizeof ( * device ) , GFP_KERNEL ) ;
if ( ! device ) {
kfree ( host ) ;
return NULL ;
}
device - > host = & host - > base ;
host - > device = device ;
return host ;
}
2015-01-16 14:27:26 +02:00
/*
* send a video mode command
*
* XXX : commands with data in MIPI_DPI_DATA ?
*/
static int dpi_send_cmd ( struct intel_dsi * intel_dsi , u32 cmd , bool hs ,
enum port port )
{
struct drm_encoder * encoder = & intel_dsi - > base . base ;
struct drm_device * dev = encoder - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
u32 mask ;
/* XXX: pipe, hs */
if ( hs )
cmd & = ~ DPI_LP_MODE ;
else
cmd | = DPI_LP_MODE ;
/* clear bit */
I915_WRITE ( MIPI_INTR_STAT ( port ) , SPL_PKT_SENT_INTERRUPT ) ;
/* XXX: old code skips write if control unchanged */
if ( cmd = = I915_READ ( MIPI_DPI_CONTROL ( port ) ) )
DRM_ERROR ( " Same special packet %02x twice in a row. \n " , cmd ) ;
I915_WRITE ( MIPI_DPI_CONTROL ( port ) , cmd ) ;
mask = SPL_PKT_SENT_INTERRUPT ;
if ( wait_for ( ( I915_READ ( MIPI_INTR_STAT ( port ) ) & mask ) = = mask , 100 ) )
DRM_ERROR ( " Video mode command 0x%08x send failed. \n " , cmd ) ;
return 0 ;
}
2013-12-10 12:14:55 +05:30
static void band_gap_reset ( struct drm_i915_private * dev_priv )
2013-08-27 15:12:24 +03:00
{
mutex_lock ( & dev_priv - > dpio_lock ) ;
2013-12-10 12:14:55 +05:30
vlv_flisdsi_write ( dev_priv , 0x08 , 0x0001 ) ;
vlv_flisdsi_write ( dev_priv , 0x0F , 0x0005 ) ;
vlv_flisdsi_write ( dev_priv , 0x0F , 0x0025 ) ;
udelay ( 150 ) ;
vlv_flisdsi_write ( dev_priv , 0x0F , 0x0000 ) ;
vlv_flisdsi_write ( dev_priv , 0x08 , 0x0000 ) ;
2013-08-27 15:12:24 +03:00
mutex_unlock ( & dev_priv - > dpio_lock ) ;
}
2013-08-27 15:12:20 +03:00
static inline bool is_vid_mode ( struct intel_dsi * intel_dsi )
{
2014-04-14 11:18:24 +05:30
return intel_dsi - > operation_mode = = INTEL_DSI_VIDEO_MODE ;
2013-08-27 15:12:20 +03:00
}
static inline bool is_cmd_mode ( struct intel_dsi * intel_dsi )
{
2014-04-14 11:18:24 +05:30
return intel_dsi - > operation_mode = = INTEL_DSI_COMMAND_MODE ;
2013-08-27 15:12:20 +03:00
}
static void intel_dsi_hot_plug ( struct intel_encoder * encoder )
{
DRM_DEBUG_KMS ( " \n " ) ;
}
static bool intel_dsi_compute_config ( struct intel_encoder * encoder ,
2015-01-15 14:55:21 +02:00
struct intel_crtc_state * config )
2013-08-27 15:12:20 +03:00
{
struct intel_dsi * intel_dsi = container_of ( encoder , struct intel_dsi ,
base ) ;
struct intel_connector * intel_connector = intel_dsi - > attached_connector ;
struct drm_display_mode * fixed_mode = intel_connector - > panel . fixed_mode ;
2015-01-15 14:55:22 +02:00
struct drm_display_mode * adjusted_mode = & config - > base . adjusted_mode ;
2013-08-27 15:12:20 +03:00
DRM_DEBUG_KMS ( " \n " ) ;
if ( fixed_mode )
intel_fixed_panel_mode ( fixed_mode , adjusted_mode ) ;
2014-07-30 20:32:37 +05:30
/* DSI uses short packets for sync events, so clear mode flags for DSI */
adjusted_mode - > flags = 0 ;
2013-08-27 15:12:20 +03:00
return true ;
}
2014-12-04 10:58:47 +05:30
static void intel_dsi_port_enable ( struct intel_encoder * encoder )
{
struct drm_device * dev = encoder - > base . dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_crtc * intel_crtc = to_intel_crtc ( encoder - > base . crtc ) ;
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( & encoder - > base ) ;
2014-12-05 14:09:28 +05:30
enum port port ;
2014-12-04 10:58:47 +05:30
u32 temp ;
2014-12-05 14:13:41 +05:30
if ( intel_dsi - > dual_link = = DSI_DUAL_LINK_FRONT_BACK ) {
temp = I915_READ ( VLV_CHICKEN_3 ) ;
temp & = ~ PIXEL_OVERLAP_CNT_MASK |
intel_dsi - > pixel_overlap < <
PIXEL_OVERLAP_CNT_SHIFT ;
I915_WRITE ( VLV_CHICKEN_3 , temp ) ;
}
2014-12-05 14:09:28 +05:30
for_each_dsi_port ( port , intel_dsi - > ports ) {
temp = I915_READ ( MIPI_PORT_CTRL ( port ) ) ;
temp & = ~ LANE_CONFIGURATION_MASK ;
temp & = ~ DUAL_LINK_MODE_MASK ;
if ( intel_dsi - > ports = = ( ( 1 < < PORT_A ) | ( 1 < < PORT_C ) ) ) {
temp | = ( intel_dsi - > dual_link - 1 )
< < DUAL_LINK_MODE_SHIFT ;
temp | = intel_crtc - > pipe ?
LANE_CONFIGURATION_DUAL_LINK_B :
LANE_CONFIGURATION_DUAL_LINK_A ;
}
/* assert ip_tg_enable signal */
I915_WRITE ( MIPI_PORT_CTRL ( port ) , temp | DPI_ENABLE ) ;
POSTING_READ ( MIPI_PORT_CTRL ( port ) ) ;
}
2014-12-04 10:58:47 +05:30
}
static void intel_dsi_port_disable ( struct intel_encoder * encoder )
{
struct drm_device * dev = encoder - > base . dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
2014-12-05 14:09:28 +05:30
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( & encoder - > base ) ;
enum port port ;
2014-12-04 10:58:47 +05:30
u32 temp ;
2014-12-05 14:09:28 +05:30
for_each_dsi_port ( port , intel_dsi - > ports ) {
/* de-assert ip_tg_enable signal */
temp = I915_READ ( MIPI_PORT_CTRL ( port ) ) ;
I915_WRITE ( MIPI_PORT_CTRL ( port ) , temp & ~ DPI_ENABLE ) ;
POSTING_READ ( MIPI_PORT_CTRL ( port ) ) ;
}
2014-12-04 10:58:47 +05:30
}
2013-12-11 17:52:05 +05:30
static void intel_dsi_device_ready ( struct intel_encoder * encoder )
2013-08-27 15:12:20 +03:00
{
2013-12-11 17:52:05 +05:30
struct drm_i915_private * dev_priv = encoder - > base . dev - > dev_private ;
2014-12-05 14:24:21 +05:30
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( & encoder - > base ) ;
enum port port ;
2013-12-11 17:52:05 +05:30
u32 val ;
2013-08-27 15:12:20 +03:00
DRM_DEBUG_KMS ( " \n " ) ;
2014-04-09 13:59:30 +05:30
mutex_lock ( & dev_priv - > dpio_lock ) ;
/* program rcomp for compliance, reduce from 50 ohms to 45 ohms
* needed everytime after power gate */
vlv_flisdsi_write ( dev_priv , 0x04 , 0x0004 ) ;
mutex_unlock ( & dev_priv - > dpio_lock ) ;
/* bandgap reset is needed after everytime we do power gate */
band_gap_reset ( dev_priv ) ;
2014-12-05 14:24:21 +05:30
for_each_dsi_port ( port , intel_dsi - > ports ) {
2014-07-03 16:35:41 +05:30
2014-12-05 14:24:21 +05:30
I915_WRITE ( MIPI_DEVICE_READY ( port ) , ULPS_STATE_ENTER ) ;
usleep_range ( 2500 , 3000 ) ;
2014-07-03 16:35:41 +05:30
2014-12-07 16:13:54 +05:30
/* Enable MIPI PHY transparent latch
* Common bit for both MIPI Port A & MIPI Port C
* No similar bit in MIPI Port C reg
*/
2015-02-05 17:08:45 +05:30
val = I915_READ ( MIPI_PORT_CTRL ( PORT_A ) ) ;
2014-12-07 16:13:54 +05:30
I915_WRITE ( MIPI_PORT_CTRL ( PORT_A ) , val | LP_OUTPUT_HOLD ) ;
2014-12-05 14:24:21 +05:30
usleep_range ( 1000 , 1500 ) ;
2014-07-03 16:35:41 +05:30
2014-12-05 14:24:21 +05:30
I915_WRITE ( MIPI_DEVICE_READY ( port ) , ULPS_STATE_EXIT ) ;
usleep_range ( 2500 , 3000 ) ;
I915_WRITE ( MIPI_DEVICE_READY ( port ) , DEVICE_READY ) ;
usleep_range ( 2500 , 3000 ) ;
}
2013-12-11 17:52:05 +05:30
}
static void intel_dsi_enable ( struct intel_encoder * encoder )
{
struct drm_device * dev = encoder - > base . dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( & encoder - > base ) ;
2015-01-22 15:01:35 +02:00
enum port port ;
2013-12-11 17:52:05 +05:30
DRM_DEBUG_KMS ( " \n " ) ;
2013-12-10 12:14:54 +05:30
2015-01-22 15:01:35 +02:00
if ( is_cmd_mode ( intel_dsi ) ) {
for_each_dsi_port ( port , intel_dsi - > ports )
I915_WRITE ( MIPI_MAX_RETURN_PKT_SIZE ( port ) , 8 * 4 ) ;
} else {
2013-08-27 15:12:20 +03:00
msleep ( 20 ) ; /* XXX */
2015-01-16 14:27:16 +02:00
for_each_dsi_port ( port , intel_dsi - > ports )
2015-01-16 14:27:26 +02:00
dpi_send_cmd ( intel_dsi , TURN_ON , false , port ) ;
2013-08-27 15:12:20 +03:00
msleep ( 100 ) ;
2015-01-23 15:30:56 +02:00
drm_panel_enable ( intel_dsi - > panel ) ;
2014-04-09 13:59:31 +05:30
2015-01-16 14:27:19 +02:00
for_each_dsi_port ( port , intel_dsi - > ports )
wait_for_dsi_fifo_empty ( intel_dsi , port ) ;
2014-07-12 17:17:22 +05:30
2014-12-04 10:58:47 +05:30
intel_dsi_port_enable ( encoder ) ;
2013-08-27 15:12:20 +03:00
}
2014-04-09 13:59:31 +05:30
}
static void intel_dsi_pre_enable ( struct intel_encoder * encoder )
{
2014-04-09 13:59:32 +05:30
struct drm_device * dev = encoder - > base . dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
2014-04-09 13:59:31 +05:30
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( & encoder - > base ) ;
2014-04-09 13:59:32 +05:30
struct intel_crtc * intel_crtc = to_intel_crtc ( encoder - > base . crtc ) ;
enum pipe pipe = intel_crtc - > pipe ;
2015-01-16 14:27:19 +02:00
enum port port ;
2014-04-09 13:59:32 +05:30
u32 tmp ;
2014-04-09 13:59:31 +05:30
DRM_DEBUG_KMS ( " \n " ) ;
2014-04-09 13:59:32 +05:30
/* Disable DPOunit clock gating, can stall pipe
* and we need DPLL REFA always enabled */
tmp = I915_READ ( DPLL ( pipe ) ) ;
tmp | = DPLL_REFA_CLK_ENABLE_VLV ;
I915_WRITE ( DPLL ( pipe ) , tmp ) ;
2014-07-30 20:32:37 +05:30
/* update the hw state for DPLL */
2015-01-15 14:55:25 +02:00
intel_crtc - > config - > dpll_hw_state . dpll = DPLL_INTEGRATED_CLOCK_VLV |
2014-07-30 22:34:27 +02:00
DPLL_REFA_CLK_ENABLE_VLV ;
2014-07-30 20:32:37 +05:30
2014-04-09 13:59:32 +05:30
tmp = I915_READ ( DSPCLK_GATE_D ) ;
tmp | = DPOUNIT_CLOCK_GATE_DISABLE ;
I915_WRITE ( DSPCLK_GATE_D , tmp ) ;
2014-04-09 13:59:31 +05:30
/* put device in ready state */
intel_dsi_device_ready ( encoder ) ;
2013-08-27 15:12:20 +03:00
2014-04-14 11:18:26 +05:30
msleep ( intel_dsi - > panel_on_delay ) ;
2015-01-23 15:30:56 +02:00
drm_panel_prepare ( intel_dsi - > panel ) ;
2014-04-09 13:59:32 +05:30
2015-01-16 14:27:19 +02:00
for_each_dsi_port ( port , intel_dsi - > ports )
wait_for_dsi_fifo_empty ( intel_dsi , port ) ;
2014-07-12 17:17:22 +05:30
2014-04-09 13:59:31 +05:30
/* Enable port in pre-enable phase itself because as per hw team
* recommendation , port should be enabled befor plane & pipe */
intel_dsi_enable ( encoder ) ;
}
static void intel_dsi_enable_nop ( struct intel_encoder * encoder )
{
DRM_DEBUG_KMS ( " \n " ) ;
/* for DSI port enable has to be done before pipe
* and plane enable , so port enable is done in
* pre_enable phase itself unlike other encoders
*/
2013-08-27 15:12:20 +03:00
}
2014-05-27 19:00:09 +03:00
static void intel_dsi_pre_disable ( struct intel_encoder * encoder )
{
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( & encoder - > base ) ;
2015-01-16 14:27:16 +02:00
enum port port ;
2014-05-27 19:00:09 +03:00
DRM_DEBUG_KMS ( " \n " ) ;
if ( is_vid_mode ( intel_dsi ) ) {
/* Send Shutdown command to the panel in LP mode */
2015-01-16 14:27:16 +02:00
for_each_dsi_port ( port , intel_dsi - > ports )
2015-01-16 14:27:26 +02:00
dpi_send_cmd ( intel_dsi , SHUTDOWN , false , port ) ;
2014-05-27 19:00:09 +03:00
msleep ( 10 ) ;
}
}
2013-08-27 15:12:20 +03:00
static void intel_dsi_disable ( struct intel_encoder * encoder )
{
2013-12-11 17:52:05 +05:30
struct drm_device * dev = encoder - > base . dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
2013-08-27 15:12:20 +03:00
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( & encoder - > base ) ;
2014-12-05 14:22:44 +05:30
enum port port ;
2013-08-27 15:12:20 +03:00
u32 temp ;
DRM_DEBUG_KMS ( " \n " ) ;
if ( is_vid_mode ( intel_dsi ) ) {
2015-01-16 14:27:19 +02:00
for_each_dsi_port ( port , intel_dsi - > ports )
wait_for_dsi_fifo_empty ( intel_dsi , port ) ;
2014-07-12 17:17:22 +05:30
2014-12-04 10:58:47 +05:30
intel_dsi_port_disable ( encoder ) ;
2013-08-27 15:12:20 +03:00
msleep ( 2 ) ;
}
2014-12-05 14:22:44 +05:30
for_each_dsi_port ( port , intel_dsi - > ports ) {
/* Panel commands can be sent when clock is in LP11 */
I915_WRITE ( MIPI_DEVICE_READY ( port ) , 0x0 ) ;
2014-04-09 13:59:34 +05:30
2014-12-05 14:22:44 +05:30
temp = I915_READ ( MIPI_CTRL ( port ) ) ;
temp & = ~ ESCAPE_CLOCK_DIVIDER_MASK ;
I915_WRITE ( MIPI_CTRL ( port ) , temp |
intel_dsi - > escape_clk_div < <
ESCAPE_CLOCK_DIVIDER_SHIFT ) ;
2014-04-09 13:59:34 +05:30
2014-12-05 14:22:44 +05:30
I915_WRITE ( MIPI_EOT_DISABLE ( port ) , CLOCKSTOP ) ;
2014-04-09 13:59:34 +05:30
2014-12-05 14:22:44 +05:30
temp = I915_READ ( MIPI_DSI_FUNC_PRG ( port ) ) ;
temp & = ~ VID_MODE_FORMAT_MASK ;
I915_WRITE ( MIPI_DSI_FUNC_PRG ( port ) , temp ) ;
2014-04-09 13:59:34 +05:30
2014-12-05 14:22:44 +05:30
I915_WRITE ( MIPI_DEVICE_READY ( port ) , 0x1 ) ;
}
2013-12-11 17:52:05 +05:30
/* if disable packets are sent before sending shutdown packet then in
* some next enable sequence send turn on packet error is observed */
2015-01-23 15:30:56 +02:00
drm_panel_disable ( intel_dsi - > panel ) ;
2014-07-12 17:17:22 +05:30
2015-01-16 14:27:19 +02:00
for_each_dsi_port ( port , intel_dsi - > ports )
wait_for_dsi_fifo_empty ( intel_dsi , port ) ;
2013-08-27 15:12:20 +03:00
}
2013-12-11 17:52:05 +05:30
static void intel_dsi_clear_device_ready ( struct intel_encoder * encoder )
2013-08-27 15:12:20 +03:00
{
2013-12-11 17:52:05 +05:30
struct drm_i915_private * dev_priv = encoder - > base . dev - > dev_private ;
2014-12-05 14:22:44 +05:30
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( & encoder - > base ) ;
enum port port ;
2013-12-11 17:52:05 +05:30
u32 val ;
2013-08-27 15:12:20 +03:00
DRM_DEBUG_KMS ( " \n " ) ;
2014-12-05 14:22:44 +05:30
for_each_dsi_port ( port , intel_dsi - > ports ) {
2013-08-27 23:40:56 +03:00
2014-12-05 14:22:44 +05:30
I915_WRITE ( MIPI_DEVICE_READY ( port ) , DEVICE_READY |
ULPS_STATE_ENTER ) ;
usleep_range ( 2000 , 2500 ) ;
I915_WRITE ( MIPI_DEVICE_READY ( port ) , DEVICE_READY |
ULPS_STATE_EXIT ) ;
usleep_range ( 2000 , 2500 ) ;
I915_WRITE ( MIPI_DEVICE_READY ( port ) , DEVICE_READY |
ULPS_STATE_ENTER ) ;
usleep_range ( 2000 , 2500 ) ;
/* Wait till Clock lanes are in LP-00 state for MIPI Port A
* only . MIPI Port C has no similar bit for checking
*/
if ( wait_for ( ( ( I915_READ ( MIPI_PORT_CTRL ( PORT_A ) ) & AFE_LATCHOUT )
= = 0x00000 ) , 30 ) )
DRM_ERROR ( " DSI LP not going Low \n " ) ;
/* Disable MIPI PHY transparent latch
* Common bit for both MIPI Port A & MIPI Port C
*/
2015-02-05 17:08:45 +05:30
val = I915_READ ( MIPI_PORT_CTRL ( PORT_A ) ) ;
2014-12-05 14:22:44 +05:30
I915_WRITE ( MIPI_PORT_CTRL ( PORT_A ) , val & ~ LP_OUTPUT_HOLD ) ;
usleep_range ( 1000 , 1500 ) ;
I915_WRITE ( MIPI_DEVICE_READY ( port ) , 0x00 ) ;
usleep_range ( 2000 , 2500 ) ;
}
2013-12-11 17:52:05 +05:30
2013-08-27 23:40:56 +03:00
vlv_disable_dsi_pll ( encoder ) ;
2013-08-27 15:12:20 +03:00
}
2014-04-09 13:59:32 +05:30
2013-12-11 17:52:05 +05:30
static void intel_dsi_post_disable ( struct intel_encoder * encoder )
{
2014-04-09 13:59:32 +05:30
struct drm_i915_private * dev_priv = encoder - > base . dev - > dev_private ;
2013-12-11 17:52:05 +05:30
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( & encoder - > base ) ;
2014-04-09 13:59:32 +05:30
u32 val ;
2013-12-11 17:52:05 +05:30
DRM_DEBUG_KMS ( " \n " ) ;
2014-05-27 19:00:09 +03:00
intel_dsi_disable ( encoder ) ;
2013-12-11 17:52:05 +05:30
intel_dsi_clear_device_ready ( encoder ) ;
2014-04-09 13:59:32 +05:30
val = I915_READ ( DSPCLK_GATE_D ) ;
val & = ~ DPOUNIT_CLOCK_GATE_DISABLE ;
I915_WRITE ( DSPCLK_GATE_D , val ) ;
2015-01-23 15:30:56 +02:00
drm_panel_unprepare ( intel_dsi - > panel ) ;
2014-04-14 11:18:26 +05:30
msleep ( intel_dsi - > panel_off_delay ) ;
msleep ( intel_dsi - > panel_pwr_cycle_delay ) ;
2013-12-11 17:52:05 +05:30
}
2013-08-27 15:12:20 +03:00
static bool intel_dsi_get_hw_state ( struct intel_encoder * encoder ,
enum pipe * pipe )
{
struct drm_i915_private * dev_priv = encoder - > base . dev - > dev_private ;
2014-12-09 10:59:20 +05:30
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( & encoder - > base ) ;
struct drm_device * dev = encoder - > base . dev ;
2014-03-05 16:20:54 +02:00
enum intel_display_power_domain power_domain ;
2014-12-09 10:59:20 +05:30
u32 dpi_enabled , func ;
2014-11-14 16:54:21 +02:00
enum port port ;
2013-08-27 15:12:20 +03:00
DRM_DEBUG_KMS ( " \n " ) ;
2014-03-05 16:20:54 +02:00
power_domain = intel_display_port_power_domain ( encoder ) ;
2014-09-30 10:56:39 +02:00
if ( ! intel_display_power_is_enabled ( dev_priv , power_domain ) )
2014-03-05 16:20:54 +02:00
return false ;
2013-08-27 15:12:20 +03:00
/* XXX: this only works for one DSI output */
2014-12-09 10:59:20 +05:30
for_each_dsi_port ( port , intel_dsi - > ports ) {
2014-11-14 16:54:21 +02:00
func = I915_READ ( MIPI_DSI_FUNC_PRG ( port ) ) ;
2014-12-09 10:59:20 +05:30
dpi_enabled = I915_READ ( MIPI_PORT_CTRL ( port ) ) &
DPI_ENABLE ;
/* Due to some hardware limitations on BYT, MIPI Port C DPI
* Enable bit does not get set . To check whether DSI Port C
* was enabled in BIOS , check the Pipe B enable bit
*/
if ( IS_VALLEYVIEW ( dev ) & & ! IS_CHERRYVIEW ( dev ) & &
( port = = PORT_C ) )
dpi_enabled = I915_READ ( PIPECONF ( PIPE_B ) ) &
PIPECONF_ENABLE ;
2013-08-27 15:12:20 +03:00
2014-12-09 10:59:20 +05:30
if ( dpi_enabled | | ( func & CMD_MODE_DATA_WIDTH_MASK ) ) {
2014-11-14 16:54:21 +02:00
if ( I915_READ ( MIPI_DEVICE_READY ( port ) ) & DEVICE_READY ) {
2014-12-09 10:59:20 +05:30
* pipe = port = = PORT_A ? PIPE_A : PIPE_B ;
2013-08-27 15:12:20 +03:00
return true ;
}
}
}
return false ;
}
static void intel_dsi_get_config ( struct intel_encoder * encoder ,
2015-01-15 14:55:21 +02:00
struct intel_crtc_state * pipe_config )
2013-08-27 15:12:20 +03:00
{
2014-07-30 20:32:37 +05:30
u32 pclk ;
2013-08-27 15:12:20 +03:00
DRM_DEBUG_KMS ( " \n " ) ;
2014-07-30 20:32:37 +05:30
/*
* DPLL_MD is not used in case of DSI , reading will get some default value
* set dpll_md = 0
*/
pipe_config - > dpll_hw_state . dpll_md = 0 ;
pclk = vlv_get_dsi_pclk ( encoder , pipe_config - > pipe_bpp ) ;
if ( ! pclk )
return ;
2015-01-15 14:55:22 +02:00
pipe_config - > base . adjusted_mode . crtc_clock = pclk ;
2014-07-30 20:32:37 +05:30
pipe_config - > port_clock = pclk ;
2013-08-27 15:12:20 +03:00
}
2013-11-28 15:29:18 +00:00
static enum drm_mode_status
intel_dsi_mode_valid ( struct drm_connector * connector ,
struct drm_display_mode * mode )
2013-08-27 15:12:20 +03:00
{
struct intel_connector * intel_connector = to_intel_connector ( connector ) ;
struct drm_display_mode * fixed_mode = intel_connector - > panel . fixed_mode ;
DRM_DEBUG_KMS ( " \n " ) ;
if ( mode - > flags & DRM_MODE_FLAG_DBLSCAN ) {
DRM_DEBUG_KMS ( " MODE_NO_DBLESCAN \n " ) ;
return MODE_NO_DBLESCAN ;
}
if ( fixed_mode ) {
if ( mode - > hdisplay > fixed_mode - > hdisplay )
return MODE_PANEL ;
if ( mode - > vdisplay > fixed_mode - > vdisplay )
return MODE_PANEL ;
}
2015-01-16 14:27:20 +02:00
return MODE_OK ;
2013-08-27 15:12:20 +03:00
}
/* return txclkesc cycles in terms of divider and duration in us */
static u16 txclkesc ( u32 divider , unsigned int us )
{
switch ( divider ) {
case ESCAPE_CLOCK_DIVIDER_1 :
default :
return 20 * us ;
case ESCAPE_CLOCK_DIVIDER_2 :
return 10 * us ;
case ESCAPE_CLOCK_DIVIDER_4 :
return 5 * us ;
}
}
/* return pixels in terms of txbyteclkhs */
2014-07-30 20:34:57 +05:30
static u16 txbyteclkhs ( u16 pixels , int bpp , int lane_count ,
u16 burst_mode_ratio )
2013-08-27 15:12:20 +03:00
{
2014-07-30 20:34:57 +05:30
return DIV_ROUND_UP ( DIV_ROUND_UP ( pixels * bpp * burst_mode_ratio ,
2014-07-30 22:34:27 +02:00
8 * 100 ) , lane_count ) ;
2013-08-27 15:12:20 +03:00
}
static void set_dsi_timings ( struct drm_encoder * encoder ,
const struct drm_display_mode * mode )
{
struct drm_device * dev = encoder - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_crtc * intel_crtc = to_intel_crtc ( encoder - > crtc ) ;
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( encoder ) ;
2014-12-04 10:58:54 +05:30
enum port port ;
2015-01-15 14:55:25 +02:00
unsigned int bpp = intel_crtc - > config - > pipe_bpp ;
2013-08-27 15:12:20 +03:00
unsigned int lane_count = intel_dsi - > lane_count ;
u16 hactive , hfp , hsync , hbp , vfp , vsync , vbp ;
hactive = mode - > hdisplay ;
hfp = mode - > hsync_start - mode - > hdisplay ;
hsync = mode - > hsync_end - mode - > hsync_start ;
hbp = mode - > htotal - mode - > hsync_end ;
2014-12-04 10:58:54 +05:30
if ( intel_dsi - > dual_link ) {
hactive / = 2 ;
if ( intel_dsi - > dual_link = = DSI_DUAL_LINK_FRONT_BACK )
hactive + = intel_dsi - > pixel_overlap ;
hfp / = 2 ;
hsync / = 2 ;
hbp / = 2 ;
}
2013-08-27 15:12:20 +03:00
vfp = mode - > vsync_start - mode - > vdisplay ;
vsync = mode - > vsync_end - mode - > vsync_start ;
vbp = mode - > vtotal - mode - > vsync_end ;
/* horizontal values are in terms of high speed byte clock */
2014-07-30 20:34:57 +05:30
hactive = txbyteclkhs ( hactive , bpp , lane_count ,
2014-07-30 22:34:27 +02:00
intel_dsi - > burst_mode_ratio ) ;
2014-07-30 20:34:57 +05:30
hfp = txbyteclkhs ( hfp , bpp , lane_count , intel_dsi - > burst_mode_ratio ) ;
hsync = txbyteclkhs ( hsync , bpp , lane_count ,
2014-07-30 22:34:27 +02:00
intel_dsi - > burst_mode_ratio ) ;
2014-07-30 20:34:57 +05:30
hbp = txbyteclkhs ( hbp , bpp , lane_count , intel_dsi - > burst_mode_ratio ) ;
2013-08-27 15:12:20 +03:00
2014-12-04 10:58:54 +05:30
for_each_dsi_port ( port , intel_dsi - > ports ) {
I915_WRITE ( MIPI_HACTIVE_AREA_COUNT ( port ) , hactive ) ;
I915_WRITE ( MIPI_HFP_COUNT ( port ) , hfp ) ;
/* meaningful for video mode non-burst sync pulse mode only,
* can be zero for non - burst sync events and burst modes */
I915_WRITE ( MIPI_HSYNC_PADDING_COUNT ( port ) , hsync ) ;
I915_WRITE ( MIPI_HBP_COUNT ( port ) , hbp ) ;
/* vertical values are in terms of lines */
I915_WRITE ( MIPI_VFP_COUNT ( port ) , vfp ) ;
I915_WRITE ( MIPI_VSYNC_PADDING_COUNT ( port ) , vsync ) ;
I915_WRITE ( MIPI_VBP_COUNT ( port ) , vbp ) ;
}
2013-08-27 15:12:20 +03:00
}
2014-04-24 23:54:59 +02:00
static void intel_dsi_prepare ( struct intel_encoder * intel_encoder )
2013-08-27 15:12:20 +03:00
{
struct drm_encoder * encoder = & intel_encoder - > base ;
struct drm_device * dev = encoder - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_crtc * intel_crtc = to_intel_crtc ( encoder - > crtc ) ;
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( encoder ) ;
struct drm_display_mode * adjusted_mode =
2015-01-15 14:55:25 +02:00
& intel_crtc - > config - > base . adjusted_mode ;
2014-12-05 14:24:21 +05:30
enum port port ;
2015-01-15 14:55:25 +02:00
unsigned int bpp = intel_crtc - > config - > pipe_bpp ;
2013-08-27 15:12:20 +03:00
u32 val , tmp ;
2014-12-05 14:24:21 +05:30
u16 mode_hdisplay ;
2013-08-27 15:12:20 +03:00
2014-11-14 16:54:21 +02:00
DRM_DEBUG_KMS ( " pipe %c \n " , pipe_name ( intel_crtc - > pipe ) ) ;
2013-08-27 15:12:20 +03:00
2014-12-05 14:24:21 +05:30
mode_hdisplay = adjusted_mode - > hdisplay ;
2013-08-27 15:12:20 +03:00
2014-12-05 14:24:21 +05:30
if ( intel_dsi - > dual_link ) {
mode_hdisplay / = 2 ;
if ( intel_dsi - > dual_link = = DSI_DUAL_LINK_FRONT_BACK )
mode_hdisplay + = intel_dsi - > pixel_overlap ;
}
2013-08-27 15:12:20 +03:00
2014-12-05 14:24:21 +05:30
for_each_dsi_port ( port , intel_dsi - > ports ) {
/* escape clock divider, 20MHz, shared for A and C.
* device ready must be off when doing this ! txclkesc ? */
tmp = I915_READ ( MIPI_CTRL ( PORT_A ) ) ;
tmp & = ~ ESCAPE_CLOCK_DIVIDER_MASK ;
I915_WRITE ( MIPI_CTRL ( PORT_A ) , tmp | ESCAPE_CLOCK_DIVIDER_1 ) ;
/* read request priority is per pipe */
tmp = I915_READ ( MIPI_CTRL ( port ) ) ;
tmp & = ~ READ_REQUEST_PRIORITY_MASK ;
I915_WRITE ( MIPI_CTRL ( port ) , tmp | READ_REQUEST_PRIORITY_HIGH ) ;
/* XXX: why here, why like this? handling in irq handler?! */
I915_WRITE ( MIPI_INTR_STAT ( port ) , 0xffffffff ) ;
I915_WRITE ( MIPI_INTR_EN ( port ) , 0xffffffff ) ;
I915_WRITE ( MIPI_DPHY_PARAM ( port ) , intel_dsi - > dphy_reg ) ;
I915_WRITE ( MIPI_DPI_RESOLUTION ( port ) ,
adjusted_mode - > vdisplay < < VERTICAL_ADDRESS_SHIFT |
mode_hdisplay < < HORIZONTAL_ADDRESS_SHIFT ) ;
}
2013-08-27 15:12:20 +03:00
set_dsi_timings ( encoder , adjusted_mode ) ;
val = intel_dsi - > lane_count < < DATA_LANES_PRG_REG_SHIFT ;
if ( is_cmd_mode ( intel_dsi ) ) {
val | = intel_dsi - > channel < < CMD_MODE_CHANNEL_NUMBER_SHIFT ;
val | = CMD_MODE_DATA_WIDTH_8_BIT ; /* XXX */
} else {
val | = intel_dsi - > channel < < VID_MODE_CHANNEL_NUMBER_SHIFT ;
/* XXX: cross-check bpp vs. pixel format? */
val | = intel_dsi - > pixel_format ;
}
2014-12-05 14:24:21 +05:30
tmp = 0 ;
if ( intel_dsi - > eotp_pkt = = 0 )
tmp | = EOT_DISABLE ;
if ( intel_dsi - > clock_stop )
tmp | = CLOCKSTOP ;
2013-08-27 15:12:20 +03:00
2014-12-05 14:24:21 +05:30
for_each_dsi_port ( port , intel_dsi - > ports ) {
I915_WRITE ( MIPI_DSI_FUNC_PRG ( port ) , val ) ;
/* timeouts for recovery. one frame IIUC. if counter expires,
* EOT and stop state . */
/*
* In burst mode , value greater than one DPI line Time in byte
* clock ( txbyteclkhs ) To timeout this timer 1 + of the above
* said value is recommended .
*
* In non - burst mode , Value greater than one DPI frame time in
* byte clock ( txbyteclkhs ) To timeout this timer 1 + of the above
* said value is recommended .
*
* In DBI only mode , value greater than one DBI frame time in
* byte clock ( txbyteclkhs ) To timeout this timer 1 + of the above
* said value is recommended .
*/
2013-08-27 15:12:20 +03:00
2014-12-05 14:24:21 +05:30
if ( is_vid_mode ( intel_dsi ) & &
intel_dsi - > video_mode_format = = VIDEO_MODE_BURST ) {
I915_WRITE ( MIPI_HS_TX_TIMEOUT ( port ) ,
txbyteclkhs ( adjusted_mode - > htotal , bpp ,
intel_dsi - > lane_count ,
intel_dsi - > burst_mode_ratio ) + 1 ) ;
} else {
I915_WRITE ( MIPI_HS_TX_TIMEOUT ( port ) ,
txbyteclkhs ( adjusted_mode - > vtotal *
adjusted_mode - > htotal ,
bpp , intel_dsi - > lane_count ,
intel_dsi - > burst_mode_ratio ) + 1 ) ;
}
I915_WRITE ( MIPI_LP_RX_TIMEOUT ( port ) , intel_dsi - > lp_rx_timeout ) ;
I915_WRITE ( MIPI_TURN_AROUND_TIMEOUT ( port ) ,
intel_dsi - > turn_arnd_val ) ;
I915_WRITE ( MIPI_DEVICE_RESET_TIMER ( port ) ,
intel_dsi - > rst_timer_val ) ;
2014-04-09 13:59:33 +05:30
2014-12-05 14:24:21 +05:30
/* dphy stuff */
2014-04-09 13:59:33 +05:30
2014-12-05 14:24:21 +05:30
/* in terms of low power clock */
I915_WRITE ( MIPI_INIT_COUNT ( port ) ,
txclkesc ( intel_dsi - > escape_clk_div , 100 ) ) ;
2013-08-27 15:12:20 +03:00
2014-12-05 14:24:21 +05:30
/* recovery disables */
2015-02-03 12:17:35 +05:30
I915_WRITE ( MIPI_EOT_DISABLE ( port ) , tmp ) ;
2014-04-14 11:18:25 +05:30
2014-12-05 14:24:21 +05:30
/* in terms of low power clock */
I915_WRITE ( MIPI_INIT_COUNT ( port ) , intel_dsi - > init_count ) ;
2013-08-27 15:12:20 +03:00
2014-12-05 14:24:21 +05:30
/* in terms of txbyteclkhs. actual high to low switch +
* MIPI_STOP_STATE_STALL * MIPI_LP_BYTECLK .
*
* XXX : write MIPI_STOP_STATE_STALL ?
*/
I915_WRITE ( MIPI_HIGH_LOW_SWITCH_COUNT ( port ) ,
intel_dsi - > hs_to_lp_count ) ;
/* XXX: low power clock equivalence in terms of byte clock.
* the number of byte clocks occupied in one low power clock .
* based on txbyteclkhs and txclkesc .
* txclkesc time / txbyteclk time * ( 105 + MIPI_STOP_STATE_STALL
* ) / 105. ? ? ?
*/
I915_WRITE ( MIPI_LP_BYTECLK ( port ) , intel_dsi - > lp_byte_clk ) ;
/* the bw essential for transmitting 16 long packets containing
* 252 bytes meant for dcs write memory command is programmed in
* this register in terms of byte clocks . based on dsi transfer
* rate and the number of lanes configured the time taken to
* transmit 16 long packets in a dsi stream varies . */
I915_WRITE ( MIPI_DBI_BW_CTRL ( port ) , intel_dsi - > bw_timer ) ;
I915_WRITE ( MIPI_CLK_LANE_SWITCH_TIME_CNT ( port ) ,
intel_dsi - > clk_lp_to_hs_count < < LP_HS_SSW_CNT_SHIFT |
intel_dsi - > clk_hs_to_lp_count < < HS_LP_PWR_SW_CNT_SHIFT ) ;
if ( is_vid_mode ( intel_dsi ) )
/* Some panels might have resolution which is not a
* multiple of 64 like 1366 x 768. Enable RANDOM
* resolution support for such panels by default */
I915_WRITE ( MIPI_VIDEO_MODE_FORMAT ( port ) ,
intel_dsi - > video_frmt_cfg_bits |
intel_dsi - > video_mode_format |
IP_TG_CONFIG |
RANDOM_DPI_DISPLAY_RESOLUTION ) ;
}
2013-08-27 15:12:20 +03:00
}
2014-04-24 23:54:59 +02:00
static void intel_dsi_pre_pll_enable ( struct intel_encoder * encoder )
{
DRM_DEBUG_KMS ( " \n " ) ;
intel_dsi_prepare ( encoder ) ;
vlv_enable_dsi_pll ( encoder ) ;
}
2013-08-27 15:12:20 +03:00
static enum drm_connector_status
intel_dsi_detect ( struct drm_connector * connector , bool force )
{
2015-01-16 14:27:20 +02:00
return connector_status_connected ;
2013-08-27 15:12:20 +03:00
}
static int intel_dsi_get_modes ( struct drm_connector * connector )
{
struct intel_connector * intel_connector = to_intel_connector ( connector ) ;
struct drm_display_mode * mode ;
DRM_DEBUG_KMS ( " \n " ) ;
if ( ! intel_connector - > panel . fixed_mode ) {
DRM_DEBUG_KMS ( " no fixed mode \n " ) ;
return 0 ;
}
mode = drm_mode_duplicate ( connector - > dev ,
intel_connector - > panel . fixed_mode ) ;
if ( ! mode ) {
DRM_DEBUG_KMS ( " drm_mode_duplicate failed \n " ) ;
return 0 ;
}
drm_mode_probed_add ( connector , mode ) ;
return 1 ;
}
2015-01-23 15:30:56 +02:00
static void intel_dsi_connector_destroy ( struct drm_connector * connector )
2013-08-27 15:12:20 +03:00
{
struct intel_connector * intel_connector = to_intel_connector ( connector ) ;
DRM_DEBUG_KMS ( " \n " ) ;
intel_panel_fini ( & intel_connector - > panel ) ;
drm_connector_cleanup ( connector ) ;
kfree ( connector ) ;
}
2015-01-23 15:30:56 +02:00
static void intel_dsi_encoder_destroy ( struct drm_encoder * encoder )
{
struct intel_dsi * intel_dsi = enc_to_intel_dsi ( encoder ) ;
if ( intel_dsi - > panel ) {
drm_panel_detach ( intel_dsi - > panel ) ;
/* XXX: Logically this call belongs in the panel driver. */
drm_panel_remove ( intel_dsi - > panel ) ;
}
intel_encoder_destroy ( encoder ) ;
}
2013-08-27 15:12:20 +03:00
static const struct drm_encoder_funcs intel_dsi_funcs = {
2015-01-23 15:30:56 +02:00
. destroy = intel_dsi_encoder_destroy ,
2013-08-27 15:12:20 +03:00
} ;
static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs = {
. get_modes = intel_dsi_get_modes ,
. mode_valid = intel_dsi_mode_valid ,
. best_encoder = intel_best_encoder ,
} ;
static const struct drm_connector_funcs intel_dsi_connector_funcs = {
. dpms = intel_connector_dpms ,
. detect = intel_dsi_detect ,
2015-01-23 15:30:56 +02:00
. destroy = intel_dsi_connector_destroy ,
2013-08-27 15:12:20 +03:00
. fill_modes = drm_helper_probe_single_connector_modes ,
2015-01-22 16:51:27 -08:00
. atomic_get_property = intel_connector_atomic_get_property ,
2015-01-22 16:50:32 -08:00
. atomic_destroy_state = drm_atomic_helper_connector_destroy_state ,
2015-03-20 16:18:06 +02:00
. atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state ,
2013-08-27 15:12:20 +03:00
} ;
2014-05-28 12:30:56 +01:00
void intel_dsi_init ( struct drm_device * dev )
2013-08-27 15:12:20 +03:00
{
struct intel_dsi * intel_dsi ;
struct intel_encoder * intel_encoder ;
struct drm_encoder * encoder ;
struct intel_connector * intel_connector ;
struct drm_connector * connector ;
2015-01-23 15:30:56 +02:00
struct drm_display_mode * scan , * fixed_mode = NULL ;
2014-05-19 20:54:03 +05:30
struct drm_i915_private * dev_priv = dev - > dev_private ;
2015-01-16 14:27:23 +02:00
enum port port ;
2013-08-27 15:12:20 +03:00
unsigned int i ;
DRM_DEBUG_KMS ( " \n " ) ;
2014-05-27 19:33:59 +05:30
/* There is no detection method for MIPI so rely on VBT */
if ( ! dev_priv - > vbt . has_mipi )
2014-05-28 12:30:56 +01:00
return ;
2014-05-27 19:33:59 +05:30
2014-06-13 21:51:22 +02:00
if ( IS_VALLEYVIEW ( dev ) ) {
dev_priv - > mipi_mmio_base = VLV_MIPI_BASE ;
} else {
DRM_ERROR ( " Unsupported Mipi device to reg base " ) ;
return ;
}
2014-05-27 19:33:59 +05:30
2013-08-27 15:12:20 +03:00
intel_dsi = kzalloc ( sizeof ( * intel_dsi ) , GFP_KERNEL ) ;
if ( ! intel_dsi )
2014-05-28 12:30:56 +01:00
return ;
2013-08-27 15:12:20 +03:00
intel_connector = kzalloc ( sizeof ( * intel_connector ) , GFP_KERNEL ) ;
if ( ! intel_connector ) {
kfree ( intel_dsi ) ;
2014-05-28 12:30:56 +01:00
return ;
2013-08-27 15:12:20 +03:00
}
intel_encoder = & intel_dsi - > base ;
encoder = & intel_encoder - > base ;
intel_dsi - > attached_connector = intel_connector ;
connector = & intel_connector - > base ;
drm_encoder_init ( dev , encoder , & intel_dsi_funcs , DRM_MODE_ENCODER_DSI ) ;
/* XXX: very likely not all of these are needed */
intel_encoder - > hot_plug = intel_dsi_hot_plug ;
intel_encoder - > compute_config = intel_dsi_compute_config ;
intel_encoder - > pre_pll_enable = intel_dsi_pre_pll_enable ;
intel_encoder - > pre_enable = intel_dsi_pre_enable ;
2014-04-09 13:59:31 +05:30
intel_encoder - > enable = intel_dsi_enable_nop ;
2014-05-27 19:00:09 +03:00
intel_encoder - > disable = intel_dsi_pre_disable ;
2013-08-27 15:12:20 +03:00
intel_encoder - > post_disable = intel_dsi_post_disable ;
intel_encoder - > get_hw_state = intel_dsi_get_hw_state ;
intel_encoder - > get_config = intel_dsi_get_config ;
intel_connector - > get_hw_state = intel_connector_get_hw_state ;
2014-02-11 17:12:48 +02:00
intel_connector - > unregister = intel_connector_unregister ;
2013-08-27 15:12:20 +03:00
2014-11-14 16:54:21 +02:00
/* Pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI port C */
2015-01-16 14:27:23 +02:00
if ( dev_priv - > vbt . dsi . config - > dual_link ) {
/* XXX: does dual link work on either pipe? */
intel_encoder - > crtc_mask = ( 1 < < PIPE_A ) ;
intel_dsi - > ports = ( ( 1 < < PORT_A ) | ( 1 < < PORT_C ) ) ;
} else if ( dev_priv - > vbt . dsi . port = = DVO_PORT_MIPIA ) {
2014-11-14 16:54:21 +02:00
intel_encoder - > crtc_mask = ( 1 < < PIPE_A ) ;
2014-11-14 16:54:22 +02:00
intel_dsi - > ports = ( 1 < < PORT_A ) ;
} else if ( dev_priv - > vbt . dsi . port = = DVO_PORT_MIPIC ) {
2014-11-14 16:54:21 +02:00
intel_encoder - > crtc_mask = ( 1 < < PIPE_B ) ;
2014-11-14 16:54:22 +02:00
intel_dsi - > ports = ( 1 < < PORT_C ) ;
}
2014-11-14 16:54:21 +02:00
2015-01-16 14:27:23 +02:00
/* Create a DSI host (and a device) for each port. */
for_each_dsi_port ( port , intel_dsi - > ports ) {
struct intel_dsi_host * host ;
host = intel_dsi_host_init ( intel_dsi , port ) ;
if ( ! host )
goto err ;
intel_dsi - > dsi_hosts [ port ] = host ;
}
2015-01-23 15:30:56 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( intel_dsi_drivers ) ; i + + ) {
intel_dsi - > panel = intel_dsi_drivers [ i ] . init ( intel_dsi ,
intel_dsi_drivers [ i ] . panel_id ) ;
if ( intel_dsi - > panel )
2013-08-27 15:12:20 +03:00
break ;
}
2015-01-23 15:30:56 +02:00
if ( ! intel_dsi - > panel ) {
2013-08-27 15:12:20 +03:00
DRM_DEBUG_KMS ( " no device found \n " ) ;
goto err ;
}
intel_encoder - > type = INTEL_OUTPUT_DSI ;
2014-03-03 16:15:28 +02:00
intel_encoder - > cloneable = 0 ;
2013-08-27 15:12:20 +03:00
drm_connector_init ( dev , connector , & intel_dsi_connector_funcs ,
DRM_MODE_CONNECTOR_DSI ) ;
drm_connector_helper_add ( connector , & intel_dsi_connector_helper_funcs ) ;
connector - > display_info . subpixel_order = SubPixelHorizontalRGB ; /*XXX*/
connector - > interlace_allowed = false ;
connector - > doublescan_allowed = false ;
intel_connector_attach_encoder ( intel_connector , intel_encoder ) ;
2014-05-29 16:57:41 +01:00
drm_connector_register ( connector ) ;
2013-08-27 15:12:20 +03:00
2015-01-23 15:30:56 +02:00
drm_panel_attach ( intel_dsi - > panel , connector ) ;
mutex_lock ( & dev - > mode_config . mutex ) ;
drm_panel_get_modes ( intel_dsi - > panel ) ;
list_for_each_entry ( scan , & connector - > probed_modes , head ) {
if ( ( scan - > type & DRM_MODE_TYPE_PREFERRED ) ) {
fixed_mode = drm_mode_duplicate ( dev , scan ) ;
break ;
}
}
mutex_unlock ( & dev - > mode_config . mutex ) ;
2013-08-27 15:12:20 +03:00
if ( ! fixed_mode ) {
DRM_DEBUG_KMS ( " no fixed mode \n " ) ;
goto err ;
}
2014-02-11 14:26:36 +05:30
intel_panel_init ( & intel_connector - > panel , fixed_mode , NULL ) ;
2013-08-27 15:12:20 +03:00
2014-05-28 12:30:56 +01:00
return ;
2013-08-27 15:12:20 +03:00
err :
drm_encoder_cleanup ( & intel_encoder - > base ) ;
kfree ( intel_dsi ) ;
kfree ( intel_connector ) ;
}