[Intel-gfx] [PATCH] Enable all formats SDVO-TV support
Zhenyu Wang
zhenyuw at linux.intel.com
Mon Jun 29 03:46:46 CEST 2009
On 2009.06.26 16:43:09 +0800, ling.ma at intel.com wrote:
> Currently SDVO TV only support NTSC-M format. In this patch
> we introduce all formats available and create seting-format
> property at init time. When user dynamically chose preferred
> format by xrandr command, it will refine all modelines
> provided by SDVO device based on the chosed format, at last
> instruct SDVO device to execute.
Last time I tried this, not all formats work in testing, so
any update now?
>
> Signed-off-by: Ma Ling <ling.ma at intel.com>
> ---
> Due to some dependency, KMS vesrion need more polishing and
> will send out next week.
>
> src/i830_sdvo.c | 215 ++++++++++++++++++++++++++++++++++++++++++++------
> src/i830_sdvo_regs.h | 1 +
> 2 files changed, 190 insertions(+), 26 deletions(-)
>
> diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
> index acfe599..ceca3b2 100644
> --- a/src/i830_sdvo.c
> +++ b/src/i830_sdvo.c
> @@ -51,6 +51,31 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
> #include "i830_sdvo_regs.h"
> #include "X11/Xatom.h"
>
> +static char *tv_format_names[] = {
> + "NTSC_M" , "NTSC_J" , "NTSC_443",
> + "PAL_B" , "PAL_D" , "PAL_G" ,
> + "PAL_H" , "PAL_I" , "PAL_M" ,
> + "PAL_N" , "PAL_NC" , "PAL_60" ,
> + "SECAM_B" , "SECAM_D" , "SECAM_G" ,
> + "SECAM_K" , "SECAM_K1", "SECAM_L" ,
> + "SECAM_60" ,
> + "240m_1080i_59", "240m_1080i_60",
> + "260m_1080i_59", "260m_1080i_60",
> + "274m_1080i_50", "274m_1080i_59",
> + "274m_1080i_60", "274m_1080p_23",
> + "274m_1080p_24", "274m_1080p_25",
> + "274m_1080p_29", "274m_1080p_30",
> + "274m_1080p_50", "274m_1080p_59",
> + "274m_1080p_60", "295m_1080i_50",
> + "295m_1080p_50", "296m_720p_59" ,
> + "296m_720p_60" , "296m_720p_50" ,
> + "293m_480p_59" , "170m_480i_59" ,
> + "TURB_576i_50" , "TURB_576p_50" ,
> + "EIA_480i_60" , "EIA_480p_60" ,
> +};
> +
> +#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names))
> +
> /** SDVO driver private structure. */
> struct i830_sdvo_priv {
> /** SDVO device on SDVO I2C bus. */
> @@ -109,6 +134,9 @@ struct i830_sdvo_priv {
> * convenience.
> */
> struct i830_sdvo_tv_format tv_format;
> + char *tv_format_name;
> + char *tv_format_supported[TV_FORMAT_NUM];
> + int format_supported_num;
>
> /** supported encoding mode, used to determine whether HDMI is supported */
> struct i830_sdvo_encode encode;
> @@ -131,7 +159,10 @@ struct i830_sdvo_priv {
> /** @} */
> };
>
> +#define TV_FORMAT_NAME "TV_FORMAT"
> static Atom broadcast_atom;
> +static Atom tv_format_atom;
> +static Atom tv_format_name_atoms[TV_FORMAT_NUM];
>
> static void
> i830_sdvo_dump(ScrnInfoPtr pScrn);
> @@ -980,29 +1011,50 @@ static void i830_sdvo_set_avi_infoframe(xf86OutputPtr output,
> SDVO_HBUF_TX_VSYNC);
> }
>
> +/**
> + * This function checks the current TV format.
> + */
> +static void
> +i830_sdvo_check_tv_format(xf86OutputPtr output, char *tv_format_name,
> + struct i830_sdvo_sdtv_resolution_request *req)
> +{
> + uint64_t format_map = 0;
> + uint32_t i, size;
> +
> + for (i = 0; i < TV_FORMAT_NUM; i++)
> + if (strcmp(tv_format_name, tv_format_names[i]) == 0)
> + break;
> +
> + if (sizeof(*req) > sizeof(format_map))
> + size = sizeof(format_map);
> + else
> + size = sizeof(*req);
> +
> + memcpy(&format_map, req, size);
> + format_map = 1 << i;
> + memcpy(req, &format_map, size);
> +}
> +
> static void
> i830_sdvo_set_tv_format(xf86OutputPtr output)
> {
> ScrnInfoPtr pScrn = output->scrn;
> I830OutputPrivatePtr intel_output = output->driver_private;
> struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
> - struct i830_sdvo_tv_format *format, unset;
> + struct i830_sdvo_tv_format format;
> uint8_t status;
>
> - format = &dev_priv->tv_format;
> - memset(&unset, 0, sizeof(unset));
> - if (memcmp(format, &unset, sizeof(*format))) {
> - xf86DrvMsg(pScrn->scrnIndex, X_INFO,
> - "%s: Choosing default TV format of NTSC-M\n",
> - SDVO_NAME(dev_priv));
> - format->ntsc_m = 1;
> - i830_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format,
> - sizeof(*format));
> - status = i830_sdvo_read_response(output, NULL, 0);
> - if (status != SDVO_CMD_STATUS_SUCCESS)
> - xf86DrvMsg(pScrn->scrnIndex, X_INFO,
> - "%s: Fail to set TV format\n", SDVO_NAME(dev_priv));
> - }
> + memset(&format, 0, sizeof(struct i830_sdvo_tv_format));
> + i830_sdvo_check_tv_format(output, dev_priv->tv_format_name,
> + (struct i830_sdvo_sdtv_resolution_request *)
> + &format);
> +
> + i830_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, &format,
> + sizeof(format));
> + status = i830_sdvo_read_response(output, NULL, 0);
> + if (status != SDVO_CMD_STATUS_SUCCESS)
> + xf86DrvMsg(pScrn->scrnIndex, X_INFO,
> + "%s: Fail to set TV format\n", SDVO_NAME(dev_priv));
> }
>
> static Bool
> @@ -1610,6 +1662,15 @@ i830_sdvo_output_setup (xf86OutputPtr output, uint16_t flag)
> if (i830_sdvo_check_hdmi_encode (output))
> name_prefix = "HDMI";
> }
> + else if (flag & SDVO_OUTPUT_YPRPB0)
> + {
> + dev_priv->controlled_output = SDVO_OUTPUT_YPRPB0;
> + output->subpixel_order = SubPixelHorizontalRGB; /* XXX */
> + name_prefix="TV";
> + dev_priv->is_tv = TRUE;
> + intel_output->needs_tv_clock = TRUE;
> + }
> +
> else if (flag & SDVO_OUTPUT_SVID0)
> {
> dev_priv->controlled_output = SDVO_OUTPUT_SVID0;
> @@ -1861,23 +1922,36 @@ i830_sdvo_get_tv_mode(DisplayModePtr *head, int width, int height,
> }
>
> /**
> - * This function checks the current TV format, and chooses a default if
> - * it hasn't been set.
> + * This function get all supported TV formats
> */
> static void
> -i830_sdvo_check_tv_format(xf86OutputPtr output)
> +i830_sdvo_get_tv_formats(xf86OutputPtr output)
> {
> I830OutputPrivatePtr intel_output = output->driver_private;
> struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
> + uint64_t format_map;
> struct i830_sdvo_tv_format format;
> + uint32_t i;
> uint8_t status;
>
> - i830_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0);
> + memset(&dev_priv->tv_format, 0, sizeof(struct i830_sdvo_tv_format));
> +
> + i830_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMATS_SUPPORT, NULL, 0);
> status = i830_sdvo_read_response(output, &format, sizeof(format));
> if (status != SDVO_CMD_STATUS_SUCCESS)
> - return;
> + return;
>
> memcpy(&dev_priv->tv_format, &format, sizeof(format));
> + memcpy(&format_map, &format, sizeof(format) > sizeof(format_map) ?
> + sizeof(format_map) : sizeof(format));
> + dev_priv->format_supported_num = 0;
> + for (i = 0 ; i < TV_FORMAT_NUM; i++)
> + if (format_map & (1 << i)) {
> + dev_priv->tv_format_supported
> + [dev_priv->format_supported_num++] = tv_format_names[i];
> + }
> +
> + dev_priv->tv_format_name = dev_priv->tv_format_supported[0];
> }
>
> static DisplayModePtr
> @@ -1891,14 +1965,14 @@ i830_sdvo_get_tv_modes(xf86OutputPtr output)
> uint8_t status;
> float refresh = 60; /* XXX */
>
> - i830_sdvo_check_tv_format(output);
> + memset(&tv_res, 0, sizeof(struct i830_sdvo_sdtv_resolution_request));
> + i830_sdvo_check_tv_format(output, dev_priv->tv_format_name,
> + &tv_res);
>
> /* Read the list of supported input resolutions for the selected TV format.
> */
> - memset(&tv_res, 0, sizeof(tv_res));
> - memcpy(&tv_res, &dev_priv->tv_format, sizeof(tv_res));
> i830_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
> - &tv_res, sizeof(tv_res));
> + &tv_res, sizeof(tv_res));
> status = i830_sdvo_read_response(output, res, sizeof(*res));
> if (status != SDVO_CMD_STATUS_SUCCESS)
> return NULL;
> @@ -1976,6 +2050,7 @@ i830_sdvo_get_crtc(xf86OutputPtr output)
> }
> #endif
>
> +
> static void
> i830_sdvo_create_resources(xf86OutputPtr output)
> {
> @@ -1984,8 +2059,39 @@ i830_sdvo_create_resources(xf86OutputPtr output)
> I830OutputPrivatePtr intel_output = output->driver_private;
> struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
> INT32 broadcast_range[2];
> - int err;
> + int err, i;
> +
> + if (dev_priv->is_tv ) {
> + /* Set up the tv_format property, which takes effect on mode set
> + * and accepts strings that match exactly
> + */
> + tv_format_atom = MakeAtom(TV_FORMAT_NAME,
> + sizeof(TV_FORMAT_NAME) - 1, TRUE);
> +
> + for (i = 0; i < dev_priv->format_supported_num; i++)
> + tv_format_name_atoms[i] = MakeAtom (
> + dev_priv->tv_format_supported[i],
> + strlen (
> + dev_priv->tv_format_supported[i]),
> + TRUE);
> + err = RRConfigureOutputProperty(output->randr_output, tv_format_atom,
> + TRUE, FALSE, FALSE,
> + dev_priv->format_supported_num,
> + (INT32 *) tv_format_name_atoms);
> + if (err != 0)
> + xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
> + "RRConfigureOutputProperty error, %d\n", err);
> +
> + err = RRChangeOutputProperty (output->randr_output, tv_format_atom,
> + XA_ATOM, 32, PropModeReplace, 1,
> + &tv_format_name_atoms[0],
> + FALSE, TRUE);
> +
> + if (err != 0)
> + xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
> + "RRChangeOutputProperty error, %d\n", err);
>
> + }
> /* only R G B are 8bit color mode */
> if (pScrn->depth != 24 ||
> /* only 965G and G4X platform */
> @@ -2021,6 +2127,18 @@ i830_sdvo_create_resources(xf86OutputPtr output)
> }
> }
>
> +static int i830_sdvo_tv_mode_lookup(struct i830_sdvo_priv *dev_priv, char *val)
> +{
> + int i;
> + for (i = 0; i < dev_priv->format_supported_num; i++) {
> + if (strcmp(dev_priv->tv_format_supported[i], val) == 0) {
> + dev_priv->tv_format_name = dev_priv->tv_format_supported[i];
> + return 0;
> + }
> + }
> + return -1;
> +}
> +
> static Bool
> i830_sdvo_set_property(xf86OutputPtr output, Atom property,
> RRPropertyValuePtr value)
> @@ -2058,8 +2176,49 @@ i830_sdvo_set_property(xf86OutputPtr output, Atom property,
> i830_sdvo_write_sdvox(output, temp);
>
> dev_priv->broadcast_rgb = val;
> +
> + return TRUE;
> }
> - return TRUE;
> +
> + if (property == tv_format_atom)
> + {
> + Atom atom;
> + const char *name;
> + DisplayModePtr crtc_mode;
> +
> + if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
> + return FALSE;
> +
> + memcpy (&atom, value->data, 4);
> + name = NameForAtom (atom);
> +
> + if (i830_sdvo_tv_mode_lookup(dev_priv, (char *)name))
> + return FALSE;
> +
> + if (pI830->starting)
> + return TRUE;
> +
> + /* TV format change will generate new modelines, try
> + to probe them and update outputs. */
I don't think this is correct, SDVO TV device can accept standard
vesa modes.
> + xf86ProbeOutputModes(output->scrn, 0, 0);
> + /* Mirror output modes to scrn mode list */
> + xf86SetScrnInfoModes (output->scrn);
> +
> + for (crtc_mode = output->probed_modes; crtc_mode;
> + crtc_mode = crtc_mode->next) {
> +
> + if (output->crtc->mode.HDisplay == crtc_mode->HDisplay &&
> + output->crtc->mode.VDisplay == crtc_mode->VDisplay)
> + break;
> + }
> + if (!crtc_mode)
> + crtc_mode = output->probed_modes;
> +
> + xf86CrtcSetMode(output->crtc, crtc_mode, output->crtc->rotation,
> + output->crtc->x, output->crtc->y);
> + return TRUE;
> + }
> + return FALSE;
> }
>
> static const xf86OutputFuncsRec i830_sdvo_output_funcs = {
> @@ -2198,6 +2357,7 @@ void i830_find_sdvo_slave(ScrnInfoPtr pScrn, int output_device,
> *slave_addr = temp_slave_addr;
> return ;
> }
> +
> Bool
> i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
> {
> @@ -2327,6 +2487,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
> /* Set the input timing to the screen. Assume always input 0. */
> i830_sdvo_set_target_input(output, TRUE, FALSE);
>
> + if (dev_priv->is_tv)
> + i830_sdvo_get_tv_formats(output);
> +
> i830_sdvo_get_input_pixel_clock_range(output, &dev_priv->pixel_clock_min,
> &dev_priv->pixel_clock_max);
>
> diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
> index ab38355..2d02926 100644
> --- a/src/i830_sdvo_regs.h
> +++ b/src/i830_sdvo_regs.h
> @@ -368,6 +368,7 @@ struct i830_sdvo_tv_format {
> unsigned int pad:3;
> } __attribute__((packed));
>
> +#define SDVO_CMD_GET_TV_FORMATS_SUPPORT 0x27
> #define SDVO_CMD_GET_TV_FORMAT 0x28
>
> /** This command should be run before SetOutputTimingsPart[12] */
> --
> 1.5.4.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Open Source Technology Center, Intel ltd.
$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20090629/35f149f9/attachment.sig>
More information about the Intel-gfx
mailing list