Hi,
I am about to design in the TDA19988. But I got a bit uncertain regarding EOL for this part. No info can be found at nxp.com. The only thing I found was EOL info for the development boards E1TDA19988A (Search Results: tda19988 ).
Also, are there any programming guide for this chip? Or is the datasheet found at mouser all info available?
Thanks,
Magnus
All you guys need is NXP source deliverable.
Here it is: GitHub - joelagnel/beagle-nxp-hdmi: TDA19988 driver for Linux Kernel
This deliverable is for Linux, but exists for MCU's as vel. Both share same driver.
Read beagle-nxp-hdmi/hdmi/comps/tmdlHdmiTx/docs/14_user_doc/TRANSMITTER_TDA998X_SW_UM_Devlib.pdf at maste... on how to set up driver or port to other OS. Driver supports Linux/Android/RTOS/Bare Metal.
In my implementation for BT656 source and STM32 I included:
tmdlHdmiTx.c
tmdlHdmiTx_local.c
tmbslTDA9989_edid.c
tmbslTDA9989_HDCP.c
tmbslTDA9989_InOut.c
tmbslTDA9989_local.c
tmbslTDA9989_misc.c
tmbslTDA9989_state.c
I modified supplied templates tmdlHdmiTx_cfg.c and tmdlHdmiTx_IW.c according to that pdf (above).
And my initialization code, which uses NXP driver:
int hdmi_enable(void)
{
tda_instance *this = &our_instance;
int err = 0;
LOG("called\n");
#ifndef STM32F446xx
down(&this->driver.sem);
#endif
this->driver.omap_dss_hdmi_panel = true;
this->tda.power = tmPowerOn;
TRY(tmdlHdmiTxSetPowerState(this->tda.instance, this->tda.power));
if (err == TM_ERR_NO_RESOURCES)
{
LOG("Busy...\n");
TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
}
tmdlHdmiTxGetHPDStatus(this->tda.instance, &this->tda.hot_plug_detect);
show_video(this);
TRY_DONE:
#ifndef STM32F446xx
up(&this->driver.sem);
#endif
return err;
}
void hdcp_on(tda_instance *this)
{
int err = 0;
if (this->tda.hdcp_status != HDCP_IS_NOT_INSTALLED)
{ /* check HDCP is installed ... */
if (this->tda.hdcp_enable)
{ /* ... but requested ! */
TRY(tmdlHdmiTxSetHdcp(this->tda.instance, True)); /* switch if on */
#if defined(TMFL_TDA19989) || defined(TMFL_TDA9984)
/* hide video content until HDCP authentification is finished */
if (!this->tda.setup.simplayHd)
{
TRY(tmdlHdmiTxSetBScreen(this->tda.instance, TMDL_HDMITX_PATTERN_BLUE));
}
#endif
}
}
TRY_DONE:
(void)0;
}
/*
* Off HDCP
*/
void hdcp_off(tda_instance *this)
{
int err = 0;
if (this->tda.hdcp_status != HDCP_IS_NOT_INSTALLED)
{ /* check HDCP is installed ... */
if (this->tda.hdcp_enable)
{ /* but no more requested */
TRY(tmdlHdmiTxSetHdcp(this->tda.instance, False)); /* switch if off */
}
}
TRY_DONE:
(void)0;
}
void show_video(tda_instance *this)
{
int err = 0;
if (this->tda.rx_device_active)
{ /* check RxSens */
if (this->tda.hot_plug_detect == TMDL_HDMITX_HOTPLUG_ACTIVE)
{ /* should be useless, but legacy... */
if (this->tda.power == tmPowerOn)
{ /* check CEC or DSS didn't switch it off */
if (this->tda.src_address != 0xFFFF)
{ /* check EDID has been received */
hdcp_off(this);
TRY(tmdlHdmiTxSetInputOutput(this->tda.instance,
this->tda.setio.video_in,
this->tda.setio.video_out,
this->tda.setio.audio_in,
this->tda.setio.sink));
hdcp_on(this);
/*
Mind that SetInputOutput disable the blue color matrix settings of tmdlHdmiTxSetBScreen ...
so put tmdlHdmiTxSetBScreen (or hdcp_on) always after
*/
}
}
}
}
TRY_DONE:
(void)0;
}
int hdmi_disable(int event_tracking)
{
tda_instance *this = &our_instance;
int err = 0;
LOG("called\n");
#ifndef STM32F446xx
down(&this->driver.sem);
#endif
this->tda.power = (event_tracking ? tmPowerSuspend : tmPowerStandby);
TRY(tmdlHdmiTxSetPowerState(this->tda.instance, this->tda.power));
TRY_DONE:
this->driver.omap_dss_hdmi_panel = false;
#ifndef STM32F446xx
up(&this->driver.sem);
#endif
return err;
}
int hdmi_enable(void)
{
tda_instance *this = &our_instance;
int err = 0;
LOG("called\n");
#ifndef STM32F446xx
down(&this->driver.sem);
#endif
this->driver.omap_dss_hdmi_panel = true;
this->tda.power = tmPowerOn;
TRY(tmdlHdmiTxSetPowerState(this->tda.instance, this->tda.power));
if (err == TM_ERR_NO_RESOURCES)
{
LOG("Busy...\n");
TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
}
tmdlHdmiTxGetHPDStatus(this->tda.instance, &this->tda.hot_plug_detect);
show_video(this);
TRY_DONE:
#ifndef STM32F446xx
up(&this->driver.sem);
#endif
return err;
}
static int tx_init(void)
{
tda_instance *this = &our_instance;
// dev_t dev=0;
int err = 0;
/* Hello word */
I2C_PRINTF("%s(%s) %d.%d.%d compiled: %s %s %s\n", HDMITX_NAME, "TDA19988",
0,
0,
0,
__DATE__, __TIME__, 0);
if (this->param.verbose)
LOG(".verbose mode\n");
/*
/!\ WARNING /! \
the startup power sequence SHALL BE standby AND THEN suspend (core driver legacy...)
this is the only way to get the TDA idle but with active HDP and RxSens interrupt listening
*/
hdmi_disable(1); /* power start sequence phase 2 */
/*
/!\ WARNING /! \
if HDMI is plugged, the core driver will send HDP nor RXSENS event when beeing powered on !
So the Android HDMI service shall start by asking the HDP status using the IOCTL GET_HPD_STATUS
*/
tmdlHdmiTxGetHPDStatus(this->tda.instance,
&this->tda.hot_plug_detect); /* power start sequence phase 3 */
/* sysfs_attrs */
#ifndef STM32F446xx
comm_init(); /* create display sysfs links (not used in STM32F4XX) */
#endif
hdmi_enable();
return 0;
}
I'm in the same boat -- I'd like a technical reference manual and/or information about programming the i2c registers. :smileyhappy:
Apparently you have to sign an NDA for this, according to the support team.