Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e00f2235 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nv50-/disp: audit and version SOR_HDMI_PWR method



The full object interfaces are about to be exposed to userspace, so we
need to check for any security-related issues and version the structs
to make it easier to handle any changes we may need in the future.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 120b0c39
Loading
Loading
Loading
Loading
+26 −5
Original line number Diff line number Diff line
@@ -22,17 +22,38 @@
 * Authors: Ben Skeggs
 */

#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>

#include "nv50.h"

int
nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nv84_hdmi_ctrl(NV50_DISP_MTHD_V1)
{
	const u32 hoff = (head * 0x800);
	union {
		struct nv50_disp_sor_hdmi_pwr_v0 v0;
	} *args = data;
	u32 ctrl;
	int ret;

	if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
	nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
	if (nvif_unpack(args->v0, 0, 0, false)) {
		nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
				 "max_ac_packet %d rekey %d\n",
			 args->v0.version, args->v0.state,
			 args->v0.max_ac_packet, args->v0.rekey);
		if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
			return -EINVAL;
		ctrl  = 0x40000000 * !!args->v0.state;
		ctrl |= args->v0.max_ac_packet << 16;
		ctrl |= args->v0.rekey;
		ctrl |= 0x1f000000; /* ??? */
	} else
		return ret;

	if (!(ctrl & 0x40000000)) {
		nv_mask(priv, 0x6165a4 + hoff, 0x40000000, 0x00000000);
		nv_mask(priv, 0x616520 + hoff, 0x00000001, 0x00000000);
		nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000000);
@@ -65,6 +86,6 @@ nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
	nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */

	/* HDMI_CTRL */
	nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, data | 0x1f000000 /* ??? */);
	nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, ctrl);
	return 0;
}
+27 −6
Original line number Diff line number Diff line
@@ -22,17 +22,38 @@
 * Authors: Ben Skeggs
 */

#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>

#include "nv50.h"

int
nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nva3_hdmi_ctrl(NV50_DISP_MTHD_V1)
{
	const u32 soff = (or * 0x800);
	const u32 soff = outp->or * 0x800;
	union {
		struct nv50_disp_sor_hdmi_pwr_v0 v0;
	} *args = data;
	u32 ctrl;
	int ret;

	if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
	nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
	if (nvif_unpack(args->v0, 0, 0, false)) {
		nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
				 "max_ac_packet %d rekey %d\n",
			 args->v0.version, args->v0.state,
			 args->v0.max_ac_packet, args->v0.rekey);
		if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
			return -EINVAL;
		ctrl  = 0x40000000 * !!args->v0.state;
		ctrl |= args->v0.max_ac_packet << 16;
		ctrl |= args->v0.rekey;
		ctrl |= 0x1f000000; /* ??? */
	} else
		return ret;

	if (!(ctrl & 0x40000000)) {
		nv_mask(priv, 0x61c5a4 + soff, 0x40000000, 0x00000000);
		nv_mask(priv, 0x61c520 + soff, 0x00000001, 0x00000000);
		nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000000);
@@ -65,6 +86,6 @@ nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
	nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */

	/* HDMI_CTRL */
	nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, data | 0x1f000000 /* ??? */);
	nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, ctrl);
	return 0;
}
+25 −5
Original line number Diff line number Diff line
@@ -22,17 +22,37 @@
 * Authors: Ben Skeggs
 */

#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>

#include "nv50.h"

int
nvd0_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nvd0_hdmi_ctrl(NV50_DISP_MTHD_V1)
{
	const u32 hoff = (head * 0x800);
	union {
		struct nv50_disp_sor_hdmi_pwr_v0 v0;
	} *args = data;
	u32 ctrl;
	int ret;

	if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
	nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
	if (nvif_unpack(args->v0, 0, 0, false)) {
		nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
				 "max_ac_packet %d rekey %d\n",
			 args->v0.version, args->v0.state,
			 args->v0.max_ac_packet, args->v0.rekey);
		if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
			return -EINVAL;
		ctrl  = 0x40000000 * !!args->v0.state;
		ctrl |= args->v0.max_ac_packet << 16;
		ctrl |= args->v0.rekey;
	} else
		return ret;

	if (!(ctrl & 0x40000000)) {
		nv_mask(priv, 0x616798 + hoff, 0x40000000, 0x00000000);
		nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000000);
		nv_mask(priv, 0x616714 + hoff, 0x00000001, 0x00000000);
@@ -54,7 +74,7 @@ nvd0_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
	nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000001);

	/* HDMI_CTRL */
	nv_mask(priv, 0x616798 + hoff, 0x401f007f, data);
	nv_mask(priv, 0x616798 + hoff, 0x401f007f, ctrl);

	/* NFI, audio doesn't work without it though.. */
	nv_mask(priv, 0x616548 + hoff, 0x00000070, 0x00000000);
+4 −0
Original line number Diff line number Diff line
@@ -909,6 +909,10 @@ nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
		if (!priv->sor.hda_eld)
			return -ENODEV;
		return priv->sor.hda_eld(object, priv, data, size, head, outp);
	case NV50_DISP_MTHD_V1_SOR_HDMI_PWR:
		if (!priv->sor.hdmi)
			return -ENODEV;
		return priv->sor.hdmi(object, priv, data, size, head, outp);
	default:
		break;
	}
+4 −4
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ struct nv50_disp_priv {
		int nr;
		int (*power)(NV50_DISP_MTHD_V1);
		int (*hda_eld)(NV50_DISP_MTHD_V1);
		int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32);
		int (*hdmi)(NV50_DISP_MTHD_V1);
		u32 lvdsconf;
	} sor;
	struct {
@@ -73,9 +73,9 @@ int nv50_dac_sense(NV50_DISP_MTHD_V1);
int nva3_hda_eld(NV50_DISP_MTHD_V1);
int nvd0_hda_eld(NV50_DISP_MTHD_V1);

int nv84_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
int nva3_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
int nvd0_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
int nv84_hdmi_ctrl(NV50_DISP_MTHD_V1);
int nva3_hdmi_ctrl(NV50_DISP_MTHD_V1);
int nvd0_hdmi_ctrl(NV50_DISP_MTHD_V1);

int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32);
int nv50_sor_power(NV50_DISP_MTHD_V1);
Loading