1
1
graphics/devg/vpoutfb/tfp410ep.c

212 строки
7.6 KiB
C

/*
* (c) 2020, SWD Embedded Systems Limited, http://www.kpda.ru
*/
/*************************************************/
/* TI TFP410-EP I2C HDMI transmitter interface */
/*************************************************/
/*************************************************/
/* HEADERS */
/*************************************************/
#include "vpoutfb.h"
/*************************************************/
/* REGISTERS */
/*************************************************/
/* Registers access */
#define REGISTER( addr ) (addr)
/* Registers */
#define REGISTER_VEN_ID REGISTER( 0x00 ) /* R: 16 bit */
#define REGISTER_DEV_ID REGISTER( 0x02 ) /* R: 16 bit */
#define REGISTER_REV_ID REGISTER( 0x04 ) /* R: 8 bit */
#define REGISTER_CTL_1_MODE REGISTER( 0x08 ) /* RW: 8 bit */
#define REGISTER_CTL_2_MODE REGISTER( 0x09 ) /* RW: 8 bit */
#define REGISTER_CTL_3_MODE REGISTER( 0x0A ) /* RW: 8 bit */
#define REGISTER_CFG REGISTER( 0x0B ) /* R: 8 bit */
#define REGISTER_DE_DLY REGISTER( 0x32 ) /* RW: 8 bit */
#define REGISTER_DE_CTL REGISTER( 0x33 ) /* RW: 8 bit */
#define REGISTER_DE_TOP REGISTER( 0x34 ) /* RW: 8 bit */
#define REGISTER_DE_CNT REGISTER( 0x36 ) /* RW: 16 bit */
#define REGISTER_DE_LIN REGISTER( 0x38 ) /* RW: 16 bit */
#define REGISTER_H_RES REGISTER( 0x3A ) /* R: 16 bit */
#define REGISTER_V_RES REGISTER( 0x3C ) /* R: 16 bit */
/*************************************************/
/* HARDWARE */
/*************************************************/
/* Device VID */
#define TFP410EP_VID 0x014c
/* Device DID */
#define TFP410EP_DID 0x0410
/*************************************************/
/* I2C FUNCTIONS */
/*************************************************/
static void reg_write8( vpout_context_t *vpout, vpout_draw_context_t *vpout_draw, uint8_t port, uint8_t reg, uint8_t val )
{
disp_adapter_t *adapter = vpout->adapter;
int ret = 0;
ret = i2c_write( vpout, vpout_draw, port, vpout->hdmi[port].device.tfp410ep.bus, vpout->hdmi[port].device.tfp410ep.speed,
vpout->hdmi[port].device.tfp410ep.address, reg, &val, 1 );
if ( ret < 0 )
goto fail;
return;
fail:
disp_printf( adapter, "[vpoutfb: tfp410ep] Fatal: I2C HDMI controller register writing failed [I2C issue: port=%d, register=0x%x, status=%d]", port, reg, ret );
}
static uint8_t reg_read8( vpout_context_t *vpout, vpout_draw_context_t *vpout_draw, uint8_t port, uint8_t reg )
{
disp_adapter_t *adapter = vpout->adapter;
uint8_t val = 0;
int ret = 0;
ret = i2c_read( vpout, vpout_draw, port, vpout->hdmi[port].device.tfp410ep.bus, vpout->hdmi[port].device.tfp410ep.speed,
vpout->hdmi[port].device.tfp410ep.address, reg, &val, 1 );
if ( ret < 0 )
goto fail;
return val;
fail:
disp_printf( adapter, "[vpoutfb: tfp410ep] Fatal: I2C HDMI controller register reading failed [I2C issue: port=%d, register=0x%x, status=%d]", port, reg, ret );
return (0);
}
static uint16_t reg_read16( vpout_context_t *vpout, vpout_draw_context_t *vpout_draw, uint8_t port, uint8_t reg )
{
disp_adapter_t *adapter = vpout->adapter;
uint8_t val[2] = {0, 0};
int ret = 0;
ret = i2c_read( vpout, vpout_draw, port, vpout->hdmi[port].device.tfp410ep.bus, vpout->hdmi[port].device.tfp410ep.speed,
vpout->hdmi[port].device.tfp410ep.address, reg, &val[0], 1 );
if ( ret < 0 )
goto fail;
ret = i2c_read( vpout, vpout_draw, port, vpout->hdmi[port].device.tfp410ep.bus, vpout->hdmi[port].device.tfp410ep.speed,
vpout->hdmi[port].device.tfp410ep.address, reg + 1, &val[1], 1 );
if ( ret < 0 )
goto fail;
return (uint16_t)val[0] | ((uint16_t)val[1] << 8);
fail:
disp_printf( adapter, "[vpoutfb: tfp410ep] Fatal: I2C HDMI controller register reading failed [I2C issue: port=%d, register=0x%x, status=%d]", port, reg, ret );
return (0);
}
/*************************************************/
/* INTERFACE FUNCTIONS */
/*************************************************/
void tfp410ep_probe( vpout_context_t *vpout, vpout_draw_context_t *vpout_draw, uint8_t port_index )
{
disp_adapter_t *adapter = vpout->adapter;
if ( i2c_init( vpout, vpout_draw, vpout->hdmi[port_index].device.tfp410ep.bus, port_index ) )
{
disp_printf( adapter, "[vpoutfb: tfp410ep] Fatal: I2C HDMI controller initialization failed [I2C issue: port=%d]", port_index );
return;
}
}
void tfp410ep_reset( vpout_context_t *vpout, vpout_draw_context_t *vpout_draw, uint8_t port_index )
{
}
void tfp410ep_remove( vpout_context_t *vpout, vpout_draw_context_t *vpout_draw, uint8_t port_index )
{
i2c_fini( vpout, vpout_draw, port_index );
}
int tfp410ep_init( vpout_context_t *vpout, vpout_draw_context_t *vpout_draw, uint8_t port_index, uint32_t pixel_clock )
{
disp_adapter_t *adapter = vpout->adapter;
uint16_t vid = 0,
did = 0,
rev = 0;
/* Device detection */
vid = reg_read16( vpout, vpout_draw, port_index, REGISTER_VEN_ID );
did = reg_read16( vpout, vpout_draw, port_index, REGISTER_DEV_ID );
rev = reg_read8( vpout, vpout_draw, port_index, REGISTER_REV_ID );
if ( (vid == TFP410EP_VID) && (did == TFP410EP_DID) )
disp_printf( adapter, "[vpoutfb: tfp410ep] Info: TFP410-EP transmitter detected (%x:%x:%d)", vid, did, rev );
else {
disp_printf( adapter, "[vpoutfb: tfp410ep] Fatal: I2C HDMI controller initialization failed [found unsupported device: %x:%x]", vid, did );
goto fail;
}
return (0);
fail:
return (-1);
}
void tfp410ep_encoder_mode_set( vpout_context_t *vpout, vpout_draw_context_t *vpout_draw, uint8_t port_index, disp_crtc_settings_t *settings )
{
/* Enable transmitter 0xbe -> 0xbf */
reg_write8( vpout, vpout_draw, port_index, REGISTER_CTL_1_MODE, 0xb7 /* RIMR device only (default 0xbf)? */ );
/* Enable data deskew 0x80 -> 0x90 */
reg_write8( vpout, vpout_draw, port_index, REGISTER_CTL_3_MODE, 0x10 );
}
int tfp410ep_read_edid( vpout_context_t *vpout, vpout_draw_context_t *vpout_draw, uint8_t port_index, uint8_t *buf, int size_ )
{
disp_adapter_t *adapter = vpout->adapter;
int ddc_bus = vpout->hdmi[port_index].device.tfp410ep.ddc_bus,
ddc_port = port_index + 1,
ddc_slave = vpout->hdmi[port_index].device.tfp410ep.ddc_slave,
ret = -1;
if ( size_ != 256 )
return (-1);
if ( i2c_init( vpout, vpout_draw, ddc_bus, ddc_port ) < 0 )
{
disp_printf( adapter, "[vpoutfb: tfp410ep] Error: DDC bus detection failed (bus: %d)", ddc_bus );
goto done;
}
if ( i2c_read( vpout, vpout_draw, ddc_port, ddc_bus, 0, ddc_slave, 0, (uint8_t *)buf, size_ ) != 0 )
{
disp_printf( adapter, "[vpoutfb: tfp410ep] Error: DDC bus reading failed (bus:%d, slave: 0x%x)", ddc_bus, ddc_slave );
goto done;
} else
ret = size_;
done:
i2c_fini( vpout, vpout_draw, ddc_port );
return ret;
}