1*5dd0baa8Skettenis // SPDX-License-Identifier: GPL-2.0-only OR MIT 2*5dd0baa8Skettenis /* Copyright The Asahi Linux Contributors */ 3*5dd0baa8Skettenis 4*5dd0baa8Skettenis #include <drm/drm_modes.h> 5*5dd0baa8Skettenis #include <drm/drm_rect.h> 6*5dd0baa8Skettenis 7*5dd0baa8Skettenis #include "dcp-internal.h" 8*5dd0baa8Skettenis 9*5dd0baa8Skettenis struct apple_dcp; 10*5dd0baa8Skettenis 11*5dd0baa8Skettenis typedef void (*dcp_callback_t)(struct apple_dcp *, void *, void *); 12*5dd0baa8Skettenis 13*5dd0baa8Skettenis 14*5dd0baa8Skettenis #define DCP_THUNK_VOID(func, handle) \ 15*5dd0baa8Skettenis static void func(struct apple_dcp *dcp, bool oob, dcp_callback_t cb, \ 16*5dd0baa8Skettenis void *cookie) \ 17*5dd0baa8Skettenis { \ 18*5dd0baa8Skettenis dcp_push(dcp, oob, &dcp_methods[handle], 0, 0, NULL, cb, cookie); \ 19*5dd0baa8Skettenis } 20*5dd0baa8Skettenis 21*5dd0baa8Skettenis #define DCP_THUNK_OUT(func, handle, T) \ 22*5dd0baa8Skettenis static void func(struct apple_dcp *dcp, bool oob, dcp_callback_t cb, \ 23*5dd0baa8Skettenis void *cookie) \ 24*5dd0baa8Skettenis { \ 25*5dd0baa8Skettenis dcp_push(dcp, oob, &dcp_methods[handle], 0, sizeof(T), NULL, cb, cookie); \ 26*5dd0baa8Skettenis } 27*5dd0baa8Skettenis 28*5dd0baa8Skettenis #define DCP_THUNK_IN(func, handle, T) \ 29*5dd0baa8Skettenis static void func(struct apple_dcp *dcp, bool oob, T *data, \ 30*5dd0baa8Skettenis dcp_callback_t cb, void *cookie) \ 31*5dd0baa8Skettenis { \ 32*5dd0baa8Skettenis dcp_push(dcp, oob, &dcp_methods[handle], sizeof(T), 0, data, cb, cookie); \ 33*5dd0baa8Skettenis } 34*5dd0baa8Skettenis 35*5dd0baa8Skettenis #define DCP_THUNK_INOUT(func, handle, T_in, T_out) \ 36*5dd0baa8Skettenis static void func(struct apple_dcp *dcp, bool oob, T_in *data, \ 37*5dd0baa8Skettenis dcp_callback_t cb, void *cookie) \ 38*5dd0baa8Skettenis { \ 39*5dd0baa8Skettenis dcp_push(dcp, oob, &dcp_methods[handle], sizeof(T_in), sizeof(T_out), data, \ 40*5dd0baa8Skettenis cb, cookie); \ 41*5dd0baa8Skettenis } 42*5dd0baa8Skettenis 43*5dd0baa8Skettenis #define IOMFB_THUNK_INOUT(name) \ 44*5dd0baa8Skettenis static void iomfb_ ## name(struct apple_dcp *dcp, bool oob, \ 45*5dd0baa8Skettenis struct iomfb_ ## name ## _req *data, \ 46*5dd0baa8Skettenis dcp_callback_t cb, void *cookie) \ 47*5dd0baa8Skettenis { \ 48*5dd0baa8Skettenis dcp_push(dcp, oob, &dcp_methods[iomfbep_ ## name], \ 49*5dd0baa8Skettenis sizeof(struct iomfb_ ## name ## _req), \ 50*5dd0baa8Skettenis sizeof(struct iomfb_ ## name ## _resp), \ 51*5dd0baa8Skettenis data, cb, cookie); \ 52*5dd0baa8Skettenis } 53*5dd0baa8Skettenis 54*5dd0baa8Skettenis /* 55*5dd0baa8Skettenis * Define type-safe trampolines. Define typedefs to enforce type-safety on the 56*5dd0baa8Skettenis * input data (so if the types don't match, gcc errors out). 57*5dd0baa8Skettenis */ 58*5dd0baa8Skettenis 59*5dd0baa8Skettenis #define TRAMPOLINE_VOID(func, handler) \ 60*5dd0baa8Skettenis static bool __maybe_unused func(struct apple_dcp *dcp, int tag, void *out, void *in) \ 61*5dd0baa8Skettenis { \ 62*5dd0baa8Skettenis trace_iomfb_callback(dcp, tag, #handler); \ 63*5dd0baa8Skettenis handler(dcp); \ 64*5dd0baa8Skettenis return true; \ 65*5dd0baa8Skettenis } 66*5dd0baa8Skettenis 67*5dd0baa8Skettenis #define TRAMPOLINE_IN(func, handler, T_in) \ 68*5dd0baa8Skettenis typedef void (*callback_##handler)(struct apple_dcp *, T_in *); \ 69*5dd0baa8Skettenis \ 70*5dd0baa8Skettenis static bool __maybe_unused func(struct apple_dcp *dcp, int tag, void *out, void *in) \ 71*5dd0baa8Skettenis { \ 72*5dd0baa8Skettenis callback_##handler cb = handler; \ 73*5dd0baa8Skettenis \ 74*5dd0baa8Skettenis trace_iomfb_callback(dcp, tag, #handler); \ 75*5dd0baa8Skettenis cb(dcp, in); \ 76*5dd0baa8Skettenis return true; \ 77*5dd0baa8Skettenis } 78*5dd0baa8Skettenis 79*5dd0baa8Skettenis #define TRAMPOLINE_INOUT(func, handler, T_in, T_out) \ 80*5dd0baa8Skettenis typedef T_out (*callback_##handler)(struct apple_dcp *, T_in *); \ 81*5dd0baa8Skettenis \ 82*5dd0baa8Skettenis static bool __maybe_unused func(struct apple_dcp *dcp, int tag, void *out, void *in) \ 83*5dd0baa8Skettenis { \ 84*5dd0baa8Skettenis T_out *typed_out = out; \ 85*5dd0baa8Skettenis callback_##handler cb = handler; \ 86*5dd0baa8Skettenis \ 87*5dd0baa8Skettenis trace_iomfb_callback(dcp, tag, #handler); \ 88*5dd0baa8Skettenis *typed_out = cb(dcp, in); \ 89*5dd0baa8Skettenis return true; \ 90*5dd0baa8Skettenis } 91*5dd0baa8Skettenis 92*5dd0baa8Skettenis #define TRAMPOLINE_OUT(func, handler, T_out) \ 93*5dd0baa8Skettenis static bool __maybe_unused func(struct apple_dcp *dcp, int tag, void *out, void *in) \ 94*5dd0baa8Skettenis { \ 95*5dd0baa8Skettenis T_out *typed_out = out; \ 96*5dd0baa8Skettenis \ 97*5dd0baa8Skettenis trace_iomfb_callback(dcp, tag, #handler); \ 98*5dd0baa8Skettenis *typed_out = handler(dcp); \ 99*5dd0baa8Skettenis return true; \ 100*5dd0baa8Skettenis } 101*5dd0baa8Skettenis 102*5dd0baa8Skettenis /* Call a DCP function given by a tag */ 103*5dd0baa8Skettenis void dcp_push(struct apple_dcp *dcp, bool oob, const struct dcp_method_entry *call, 104*5dd0baa8Skettenis u32 in_len, u32 out_len, void *data, dcp_callback_t cb, 105*5dd0baa8Skettenis void *cookie); 106*5dd0baa8Skettenis 107*5dd0baa8Skettenis /* Parse a callback tag "D123" into the ID 123. Returns -EINVAL on failure. */ 108*5dd0baa8Skettenis int dcp_parse_tag(char tag[4]); 109*5dd0baa8Skettenis 110*5dd0baa8Skettenis void dcp_ack(struct apple_dcp *dcp, enum dcp_context_id context); 111*5dd0baa8Skettenis 112*5dd0baa8Skettenis /* 113*5dd0baa8Skettenis * DRM specifies rectangles as start and end coordinates. DCP specifies 114*5dd0baa8Skettenis * rectangles as a start coordinate and a width/height. Convert a DRM rectangle 115*5dd0baa8Skettenis * to a DCP rectangle. 116*5dd0baa8Skettenis */ 117*5dd0baa8Skettenis struct dcp_rect drm_to_dcp_rect(struct drm_rect *rect); 118*5dd0baa8Skettenis 119*5dd0baa8Skettenis u32 drm_format_to_dcp(u32 drm); 120*5dd0baa8Skettenis 121*5dd0baa8Skettenis /* The user may own drm_display_mode, so we need to search for our copy */ 122*5dd0baa8Skettenis struct dcp_display_mode *lookup_mode(struct apple_dcp *dcp, 123*5dd0baa8Skettenis const struct drm_display_mode *mode); 124