Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: MIT
  2
  3#include <drm/drm_atomic.h>
  4#include <drm/drm_connector.h>
  5#include <drm/drm_edid.h>
  6#include <drm/drm_print.h>
  7
  8#include <drm/display/drm_hdmi_helper.h>
  9#include <drm/display/drm_hdmi_state_helper.h>
 10
 11/**
 12 * __drm_atomic_helper_connector_hdmi_reset() - Initializes all HDMI @drm_connector_state resources
 13 * @connector: DRM connector
 14 * @new_conn_state: connector state to reset
 15 *
 16 * Initializes all HDMI resources from a @drm_connector_state without
 17 * actually allocating it. This is useful for HDMI drivers, in
 18 * combination with __drm_atomic_helper_connector_reset() or
 19 * drm_atomic_helper_connector_reset().
 20 */
 21void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector,
 22					      struct drm_connector_state *new_conn_state)
 23{
 24	unsigned int max_bpc = connector->max_bpc;
 25
 26	new_conn_state->max_bpc = max_bpc;
 27	new_conn_state->max_requested_bpc = max_bpc;
 28	new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO;
 29}
 30EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
 31
 32static const struct drm_display_mode *
 33connector_state_get_mode(const struct drm_connector_state *conn_state)
 34{
 35	struct drm_atomic_state *state;
 36	struct drm_crtc_state *crtc_state;
 37	struct drm_crtc *crtc;
 38
 39	state = conn_state->state;
 40	if (!state)
 41		return NULL;
 42
 43	crtc = conn_state->crtc;
 44	if (!crtc)
 45		return NULL;
 46
 47	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 48	if (!crtc_state)
 49		return NULL;
 50
 51	return &crtc_state->mode;
 52}
 53
 54static bool hdmi_is_limited_range(const struct drm_connector *connector,
 55				  const struct drm_connector_state *conn_state)
 56{
 57	const struct drm_display_info *info = &connector->display_info;
 58	const struct drm_display_mode *mode =
 59		connector_state_get_mode(conn_state);
 60
 61	/*
 62	 * The Broadcast RGB property only applies to RGB format, and
 63	 * i915 just assumes limited range for YCbCr output, so let's
 64	 * just do the same.
 65	 */
 66	if (conn_state->hdmi.output_format != HDMI_COLORSPACE_RGB)
 67		return true;
 68
 69	if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL)
 70		return false;
 71
 72	if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED)
 73		return true;
 74
 75	if (!info->is_hdmi)
 76		return false;
 77
 78	return drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED;
 79}
 80
 81static bool
 82sink_supports_format_bpc(const struct drm_connector *connector,
 83			 const struct drm_display_info *info,
 84			 const struct drm_display_mode *mode,
 85			 unsigned int format, unsigned int bpc)
 86{
 87	struct drm_device *dev = connector->dev;
 88	u8 vic = drm_match_cea_mode(mode);
 89
 90	/*
 91	 * CTA-861-F, section 5.4 - Color Coding & Quantization states
 92	 * that the bpc must be 8, 10, 12 or 16 except for the default
 93	 * 640x480 VIC1 where the value must be 8.
 94	 *
 95	 * The definition of default here is ambiguous but the spec
 96	 * refers to VIC1 being the default timing in several occasions
 97	 * so our understanding is that for the default timing (ie,
 98	 * VIC1), the bpc must be 8.
 99	 */
100	if (vic == 1 && bpc != 8) {
101		drm_dbg_kms(dev, "VIC1 requires a bpc of 8, got %u\n", bpc);
102		return false;
103	}
104
105	if (!info->is_hdmi &&
106	    (format != HDMI_COLORSPACE_RGB || bpc != 8)) {
107		drm_dbg_kms(dev, "DVI Monitors require an RGB output at 8 bpc\n");
108		return false;
109	}
110
111	if (!(connector->hdmi.supported_formats & BIT(format))) {
112		drm_dbg_kms(dev, "%s format unsupported by the connector.\n",
113			    drm_hdmi_connector_get_output_format_name(format));
114		return false;
115	}
116
117	switch (format) {
118	case HDMI_COLORSPACE_RGB:
119		drm_dbg_kms(dev, "RGB Format, checking the constraints.\n");
120
121		/*
122		 * In some cases, like when the EDID readout fails, or
123		 * is not an HDMI compliant EDID for some reason, the
124		 * color_formats field will be blank and not report any
125		 * format supported. In such a case, assume that RGB is
126		 * supported so we can keep things going and light up
127		 * the display.
128		 */
129		if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444))
130			drm_warn(dev, "HDMI Sink doesn't support RGB, something's wrong.\n");
131
132		if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) {
133			drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
134			return false;
135		}
136
137		if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) {
138			drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
139			return false;
140		}
141
142		drm_dbg_kms(dev, "RGB format supported in that configuration.\n");
143
144		return true;
145
146	case HDMI_COLORSPACE_YUV420:
147		/* TODO: YUV420 is unsupported at the moment. */
148		drm_dbg_kms(dev, "YUV420 format isn't supported yet.\n");
149		return false;
150
151	case HDMI_COLORSPACE_YUV422:
152		drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n");
153
154		if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
155			drm_dbg_kms(dev, "Sink doesn't support YUV422.\n");
156			return false;
157		}
158
159		if (bpc > 12) {
160			drm_dbg_kms(dev, "YUV422 only supports 12 bpc or lower.\n");
161			return false;
162		}
163
164		/*
165		 * HDMI Spec 1.3 - Section 6.5 Pixel Encodings and Color Depth
166		 * states that Deep Color is not relevant for YUV422 so we
167		 * don't need to check the Deep Color bits in the EDIDs here.
168		 */
169
170		drm_dbg_kms(dev, "YUV422 format supported in that configuration.\n");
171
172		return true;
173
174	case HDMI_COLORSPACE_YUV444:
175		drm_dbg_kms(dev, "YUV444 format, checking the constraints.\n");
176
177		if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {
178			drm_dbg_kms(dev, "Sink doesn't support YUV444.\n");
179			return false;
180		}
181
182		if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) {
183			drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
184			return false;
185		}
186
187		if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) {
188			drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
189			return false;
190		}
191
192		drm_dbg_kms(dev, "YUV444 format supported in that configuration.\n");
193
194		return true;
195	}
196
197	drm_dbg_kms(dev, "Unsupported pixel format.\n");
198	return false;
199}
200
201static enum drm_mode_status
202hdmi_clock_valid(const struct drm_connector *connector,
203		 const struct drm_display_mode *mode,
204		 unsigned long long clock)
205{
206	const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
207	const struct drm_display_info *info = &connector->display_info;
208
209	if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000)
210		return MODE_CLOCK_HIGH;
211
212	if (funcs && funcs->tmds_char_rate_valid) {
213		enum drm_mode_status status;
214
215		status = funcs->tmds_char_rate_valid(connector, mode, clock);
216		if (status != MODE_OK)
217			return status;
218	}
219
220	return MODE_OK;
221}
222
223static int
224hdmi_compute_clock(const struct drm_connector *connector,
225		   struct drm_connector_state *conn_state,
226		   const struct drm_display_mode *mode,
227		   unsigned int bpc, enum hdmi_colorspace fmt)
228{
229	enum drm_mode_status status;
230	unsigned long long clock;
231
232	clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt);
233	if (!clock)
234		return -EINVAL;
235
236	status = hdmi_clock_valid(connector, mode, clock);
237	if (status != MODE_OK)
238		return -EINVAL;
239
240	conn_state->hdmi.tmds_char_rate = clock;
241
242	return 0;
243}
244
245static bool
246hdmi_try_format_bpc(const struct drm_connector *connector,
247		    struct drm_connector_state *conn_state,
248		    const struct drm_display_mode *mode,
249		    unsigned int bpc, enum hdmi_colorspace fmt)
250{
251	const struct drm_display_info *info = &connector->display_info;
252	struct drm_device *dev = connector->dev;
253	int ret;
254
255	drm_dbg_kms(dev, "Trying %s output format\n",
256		    drm_hdmi_connector_get_output_format_name(fmt));
257
258	if (!sink_supports_format_bpc(connector, info, mode, fmt, bpc)) {
259		drm_dbg_kms(dev, "%s output format not supported with %u bpc\n",
260			    drm_hdmi_connector_get_output_format_name(fmt),
261			    bpc);
262		return false;
263	}
264
265	ret = hdmi_compute_clock(connector, conn_state, mode, bpc, fmt);
266	if (ret) {
267		drm_dbg_kms(dev, "Couldn't compute clock for %s output format and %u bpc\n",
268			    drm_hdmi_connector_get_output_format_name(fmt),
269			    bpc);
270		return false;
271	}
272
273	drm_dbg_kms(dev, "%s output format supported with %u (TMDS char rate: %llu Hz)\n",
274		    drm_hdmi_connector_get_output_format_name(fmt),
275		    bpc, conn_state->hdmi.tmds_char_rate);
276
277	return true;
278}
279
280static int
281hdmi_compute_format(const struct drm_connector *connector,
282		    struct drm_connector_state *conn_state,
283		    const struct drm_display_mode *mode,
284		    unsigned int bpc)
285{
286	struct drm_device *dev = connector->dev;
287
288	/*
289	 * TODO: Add support for YCbCr420 output for HDMI 2.0 capable
290	 * devices, for modes that only support YCbCr420.
291	 */
292	if (hdmi_try_format_bpc(connector, conn_state, mode, bpc, HDMI_COLORSPACE_RGB)) {
293		conn_state->hdmi.output_format = HDMI_COLORSPACE_RGB;
294		return 0;
295	}
296
297	drm_dbg_kms(dev, "Failed. No Format Supported for that bpc count.\n");
298
299	return -EINVAL;
300}
301
302static int
303hdmi_compute_config(const struct drm_connector *connector,
304		    struct drm_connector_state *conn_state,
305		    const struct drm_display_mode *mode)
306{
307	struct drm_device *dev = connector->dev;
308	unsigned int max_bpc = clamp_t(unsigned int,
309				       conn_state->max_bpc,
310				       8, connector->max_bpc);
311	unsigned int bpc;
312	int ret;
313
314	for (bpc = max_bpc; bpc >= 8; bpc -= 2) {
315		drm_dbg_kms(dev, "Trying with a %d bpc output\n", bpc);
316
317		ret = hdmi_compute_format(connector, conn_state, mode, bpc);
318		if (ret)
319			continue;
320
321		conn_state->hdmi.output_bpc = bpc;
322
323		drm_dbg_kms(dev,
324			    "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n",
325			    mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
326			    conn_state->hdmi.output_bpc,
327			    drm_hdmi_connector_get_output_format_name(conn_state->hdmi.output_format),
328			    conn_state->hdmi.tmds_char_rate);
329
330		return 0;
331	}
332
333	return -EINVAL;
334}
335
336static int hdmi_generate_avi_infoframe(const struct drm_connector *connector,
337				       struct drm_connector_state *conn_state)
338{
339	const struct drm_display_mode *mode =
340		connector_state_get_mode(conn_state);
341	struct drm_connector_hdmi_infoframe *infoframe =
342		&conn_state->hdmi.infoframes.avi;
343	struct hdmi_avi_infoframe *frame =
344		&infoframe->data.avi;
345	bool is_limited_range = conn_state->hdmi.is_limited_range;
346	enum hdmi_quantization_range rgb_quant_range =
347		is_limited_range ? HDMI_QUANTIZATION_RANGE_LIMITED : HDMI_QUANTIZATION_RANGE_FULL;
348	int ret;
349
350	infoframe->set = false;
351
352	ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, mode);
353	if (ret)
354		return ret;
355
356	frame->colorspace = conn_state->hdmi.output_format;
357
358	/*
359	 * FIXME: drm_hdmi_avi_infoframe_quant_range() doesn't handle
360	 * YUV formats at all at the moment, so if we ever support YUV
361	 * formats this needs to be revised.
362	 */
363	drm_hdmi_avi_infoframe_quant_range(frame, connector, mode, rgb_quant_range);
364	drm_hdmi_avi_infoframe_colorimetry(frame, conn_state);
365	drm_hdmi_avi_infoframe_bars(frame, conn_state);
366
367	infoframe->set = true;
368
369	return 0;
370}
371
372static int hdmi_generate_spd_infoframe(const struct drm_connector *connector,
373				       struct drm_connector_state *conn_state)
374{
375	struct drm_connector_hdmi_infoframe *infoframe =
376		&conn_state->hdmi.infoframes.spd;
377	struct hdmi_spd_infoframe *frame =
378		&infoframe->data.spd;
379	int ret;
380
381	infoframe->set = false;
382
383	ret = hdmi_spd_infoframe_init(frame,
384				      connector->hdmi.vendor,
385				      connector->hdmi.product);
386	if (ret)
387		return ret;
388
389	frame->sdi = HDMI_SPD_SDI_PC;
390
391	infoframe->set = true;
392
393	return 0;
394}
395
396static int hdmi_generate_hdr_infoframe(const struct drm_connector *connector,
397				       struct drm_connector_state *conn_state)
398{
399	struct drm_connector_hdmi_infoframe *infoframe =
400		&conn_state->hdmi.infoframes.hdr_drm;
401	struct hdmi_drm_infoframe *frame =
402		&infoframe->data.drm;
403	int ret;
404
405	infoframe->set = false;
406
407	if (connector->max_bpc < 10)
408		return 0;
409
410	if (!conn_state->hdr_output_metadata)
411		return 0;
412
413	ret = drm_hdmi_infoframe_set_hdr_metadata(frame, conn_state);
414	if (ret)
415		return ret;
416
417	infoframe->set = true;
418
419	return 0;
420}
421
422static int hdmi_generate_hdmi_vendor_infoframe(const struct drm_connector *connector,
423					       struct drm_connector_state *conn_state)
424{
425	const struct drm_display_info *info = &connector->display_info;
426	const struct drm_display_mode *mode =
427		connector_state_get_mode(conn_state);
428	struct drm_connector_hdmi_infoframe *infoframe =
429		&conn_state->hdmi.infoframes.hdmi;
430	struct hdmi_vendor_infoframe *frame =
431		&infoframe->data.vendor.hdmi;
432	int ret;
433
434	infoframe->set = false;
435
436	if (!info->has_hdmi_infoframe)
437		return 0;
438
439	ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, connector, mode);
440	if (ret)
441		return ret;
442
443	infoframe->set = true;
444
445	return 0;
446}
447
448static int
449hdmi_generate_infoframes(const struct drm_connector *connector,
450			 struct drm_connector_state *conn_state)
451{
452	const struct drm_display_info *info = &connector->display_info;
453	int ret;
454
455	if (!info->is_hdmi)
456		return 0;
457
458	ret = hdmi_generate_avi_infoframe(connector, conn_state);
459	if (ret)
460		return ret;
461
462	ret = hdmi_generate_spd_infoframe(connector, conn_state);
463	if (ret)
464		return ret;
465
466	/*
467	 * Audio Infoframes will be generated by ALSA, and updated by
468	 * drm_atomic_helper_connector_hdmi_update_audio_infoframe().
469	 */
470
471	ret = hdmi_generate_hdr_infoframe(connector, conn_state);
472	if (ret)
473		return ret;
474
475	ret = hdmi_generate_hdmi_vendor_infoframe(connector, conn_state);
476	if (ret)
477		return ret;
478
479	return 0;
480}
481
482/**
483 * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector atomic state
484 * @connector: DRM Connector
485 * @state: the DRM State object
486 *
487 * Provides a default connector state check handler for HDMI connectors.
488 * Checks that a desired connector update is valid, and updates various
489 * fields of derived state.
490 *
491 * RETURNS:
492 * Zero on success, or an errno code otherwise.
493 */
494int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
495					   struct drm_atomic_state *state)
496{
497	struct drm_connector_state *old_conn_state =
498		drm_atomic_get_old_connector_state(state, connector);
499	struct drm_connector_state *new_conn_state =
500		drm_atomic_get_new_connector_state(state, connector);
501	const struct drm_display_mode *mode =
502		connector_state_get_mode(new_conn_state);
503	int ret;
504
505	new_conn_state->hdmi.is_limited_range = hdmi_is_limited_range(connector, new_conn_state);
506
507	ret = hdmi_compute_config(connector, new_conn_state, mode);
508	if (ret)
509		return ret;
510
511	ret = hdmi_generate_infoframes(connector, new_conn_state);
512	if (ret)
513		return ret;
514
515	if (old_conn_state->hdmi.broadcast_rgb != new_conn_state->hdmi.broadcast_rgb ||
516	    old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc ||
517	    old_conn_state->hdmi.output_format != new_conn_state->hdmi.output_format) {
518		struct drm_crtc *crtc = new_conn_state->crtc;
519		struct drm_crtc_state *crtc_state;
520
521		crtc_state = drm_atomic_get_crtc_state(state, crtc);
522		if (IS_ERR(crtc_state))
523			return PTR_ERR(crtc_state);
524
525		crtc_state->mode_changed = true;
526	}
527
528	return 0;
529}
530EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check);
531
532static int clear_device_infoframe(struct drm_connector *connector,
533				  enum hdmi_infoframe_type type)
534{
535	const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
536	struct drm_device *dev = connector->dev;
537	int ret;
538
539	drm_dbg_kms(dev, "Clearing infoframe type 0x%x\n", type);
540
541	if (!funcs || !funcs->clear_infoframe) {
542		drm_dbg_kms(dev, "Function not implemented, bailing.\n");
543		return 0;
544	}
545
546	ret = funcs->clear_infoframe(connector, type);
547	if (ret) {
548		drm_dbg_kms(dev, "Call failed: %d\n", ret);
549		return ret;
550	}
551
552	return 0;
553}
554
555static int clear_infoframe(struct drm_connector *connector,
556			   struct drm_connector_hdmi_infoframe *old_frame)
557{
558	int ret;
559
560	ret = clear_device_infoframe(connector, old_frame->data.any.type);
561	if (ret)
562		return ret;
563
564	return 0;
565}
566
567static int write_device_infoframe(struct drm_connector *connector,
568				  union hdmi_infoframe *frame)
569{
570	const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
571	struct drm_device *dev = connector->dev;
572	u8 buffer[HDMI_INFOFRAME_SIZE(MAX)];
573	int ret;
574	int len;
575
576	drm_dbg_kms(dev, "Writing infoframe type %x\n", frame->any.type);
577
578	if (!funcs || !funcs->write_infoframe) {
579		drm_dbg_kms(dev, "Function not implemented, bailing.\n");
580		return -EINVAL;
581	}
582
583	len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer));
584	if (len < 0)
585		return len;
586
587	ret = funcs->write_infoframe(connector, frame->any.type, buffer, len);
588	if (ret) {
589		drm_dbg_kms(dev, "Call failed: %d\n", ret);
590		return ret;
591	}
592
593	return 0;
594}
595
596static int write_infoframe(struct drm_connector *connector,
597			   struct drm_connector_hdmi_infoframe *new_frame)
598{
599	int ret;
600
601	ret = write_device_infoframe(connector, &new_frame->data);
602	if (ret)
603		return ret;
604
605	return 0;
606}
607
608static int write_or_clear_infoframe(struct drm_connector *connector,
609				    struct drm_connector_hdmi_infoframe *old_frame,
610				    struct drm_connector_hdmi_infoframe *new_frame)
611{
612	if (new_frame->set)
613		return write_infoframe(connector, new_frame);
614
615	if (old_frame->set && !new_frame->set)
616		return clear_infoframe(connector, old_frame);
617
618	return 0;
619}
620
621/**
622 * drm_atomic_helper_connector_hdmi_update_infoframes - Update the Infoframes
623 * @connector: A pointer to the HDMI connector
624 * @state: The HDMI connector state to generate the infoframe from
625 *
626 * This function is meant for HDMI connector drivers to write their
627 * infoframes. It will typically be used in a
628 * @drm_connector_helper_funcs.atomic_enable implementation.
629 *
630 * Returns:
631 * Zero on success, error code on failure.
632 */
633int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector *connector,
634						       struct drm_atomic_state *state)
635{
636	struct drm_connector_state *old_conn_state =
637		drm_atomic_get_old_connector_state(state, connector);
638	struct drm_connector_state *new_conn_state =
639		drm_atomic_get_new_connector_state(state, connector);
640	struct drm_display_info *info = &connector->display_info;
641	int ret;
642
643	if (!info->is_hdmi)
644		return 0;
645
646	mutex_lock(&connector->hdmi.infoframes.lock);
647
648	ret = write_or_clear_infoframe(connector,
649				       &old_conn_state->hdmi.infoframes.avi,
650				       &new_conn_state->hdmi.infoframes.avi);
651	if (ret)
652		goto out;
653
654	if (connector->hdmi.infoframes.audio.set) {
655		ret = write_infoframe(connector,
656				      &connector->hdmi.infoframes.audio);
657		if (ret)
658			goto out;
659	}
660
661	ret = write_or_clear_infoframe(connector,
662				       &old_conn_state->hdmi.infoframes.hdr_drm,
663				       &new_conn_state->hdmi.infoframes.hdr_drm);
664	if (ret)
665		goto out;
666
667	ret = write_or_clear_infoframe(connector,
668				       &old_conn_state->hdmi.infoframes.spd,
669				       &new_conn_state->hdmi.infoframes.spd);
670	if (ret)
671		goto out;
672
673	if (info->has_hdmi_infoframe) {
674		ret = write_or_clear_infoframe(connector,
675					       &old_conn_state->hdmi.infoframes.hdmi,
676					       &new_conn_state->hdmi.infoframes.hdmi);
677		if (ret)
678			goto out;
679	}
680
681out:
682	mutex_unlock(&connector->hdmi.infoframes.lock);
683	return ret;
684}
685EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_infoframes);
686
687/**
688 * drm_atomic_helper_connector_hdmi_update_audio_infoframe - Update the Audio Infoframe
689 * @connector: A pointer to the HDMI connector
690 * @frame: A pointer to the audio infoframe to write
691 *
692 * This function is meant for HDMI connector drivers to update their
693 * audio infoframe. It will typically be used in one of the ALSA hooks
694 * (most likely prepare).
695 *
696 * Returns:
697 * Zero on success, error code on failure.
698 */
699int
700drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *connector,
701							struct hdmi_audio_infoframe *frame)
702{
703	struct drm_connector_hdmi_infoframe *infoframe =
704		&connector->hdmi.infoframes.audio;
705	struct drm_display_info *info = &connector->display_info;
706	int ret;
707
708	if (!info->is_hdmi)
709		return 0;
710
711	mutex_lock(&connector->hdmi.infoframes.lock);
712
713	memcpy(&infoframe->data, frame, sizeof(infoframe->data));
714	infoframe->set = true;
715
716	ret = write_infoframe(connector, infoframe);
717
718	mutex_unlock(&connector->hdmi.infoframes.lock);
719
720	return ret;
721}
722EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_audio_infoframe);
723
724/**
725 * drm_atomic_helper_connector_hdmi_clear_audio_infoframe - Stop sending the Audio Infoframe
726 * @connector: A pointer to the HDMI connector
727 *
728 * This function is meant for HDMI connector drivers to stop sending their
729 * audio infoframe. It will typically be used in one of the ALSA hooks
730 * (most likely shutdown).
731 *
732 * Returns:
733 * Zero on success, error code on failure.
734 */
735int
736drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector)
737{
738	struct drm_connector_hdmi_infoframe *infoframe =
739		&connector->hdmi.infoframes.audio;
740	struct drm_display_info *info = &connector->display_info;
741	int ret;
742
743	if (!info->is_hdmi)
744		return 0;
745
746	mutex_lock(&connector->hdmi.infoframes.lock);
747
748	infoframe->set = false;
749
750	ret = clear_infoframe(connector, infoframe);
751
752	memset(&infoframe->data, 0, sizeof(infoframe->data));
753
754	mutex_unlock(&connector->hdmi.infoframes.lock);
755
756	return ret;
757}
758EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_clear_audio_infoframe);