mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 08:14:15 +08:00
media: cec: make cec_get_edid_spa_location() an inline function
[ Upstream commit b915bf575d
]
This function is needed by both V4L2 and CEC, so move this to
cec.h as a static inline since there are no obvious shared
modules between the two subsystems.
This patch, together with the following ones, fixes a
dependency bug: if CEC_CORE is disabled, then building adv7604
(and other HDMI receivers) will fail because an essential
function is now stubbed out.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: <stable@vger.kernel.org> # for v4.17 and up
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
This commit is contained in:
parent
363b93186f
commit
c93155fed0
@ -22,66 +22,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <media/cec.h>
|
||||
|
||||
/*
|
||||
* This EDID is expected to be a CEA-861 compliant, which means that there are
|
||||
* at least two blocks and one or more of the extensions blocks are CEA-861
|
||||
* blocks.
|
||||
*
|
||||
* The returned location is guaranteed to be < size - 1.
|
||||
*/
|
||||
static unsigned int cec_get_edid_spa_location(const u8 *edid, unsigned int size)
|
||||
{
|
||||
unsigned int blocks = size / 128;
|
||||
unsigned int block;
|
||||
u8 d;
|
||||
|
||||
/* Sanity check: at least 2 blocks and a multiple of the block size */
|
||||
if (blocks < 2 || size % 128)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If there are fewer extension blocks than the size, then update
|
||||
* 'blocks'. It is allowed to have more extension blocks than the size,
|
||||
* since some hardware can only read e.g. 256 bytes of the EDID, even
|
||||
* though more blocks are present. The first CEA-861 extension block
|
||||
* should normally be in block 1 anyway.
|
||||
*/
|
||||
if (edid[0x7e] + 1 < blocks)
|
||||
blocks = edid[0x7e] + 1;
|
||||
|
||||
for (block = 1; block < blocks; block++) {
|
||||
unsigned int offset = block * 128;
|
||||
|
||||
/* Skip any non-CEA-861 extension blocks */
|
||||
if (edid[offset] != 0x02 || edid[offset + 1] != 0x03)
|
||||
continue;
|
||||
|
||||
/* search Vendor Specific Data Block (tag 3) */
|
||||
d = edid[offset + 2] & 0x7f;
|
||||
/* Check if there are Data Blocks */
|
||||
if (d <= 4)
|
||||
continue;
|
||||
if (d > 4) {
|
||||
unsigned int i = offset + 4;
|
||||
unsigned int end = offset + d;
|
||||
|
||||
/* Note: 'end' is always < 'size' */
|
||||
do {
|
||||
u8 tag = edid[i] >> 5;
|
||||
u8 len = edid[i] & 0x1f;
|
||||
|
||||
if (tag == 3 && len >= 5 && i + len <= end &&
|
||||
edid[i + 1] == 0x03 &&
|
||||
edid[i + 2] == 0x0c &&
|
||||
edid[i + 3] == 0x00)
|
||||
return i + 4;
|
||||
i += len + 1;
|
||||
} while (i < end);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
|
||||
unsigned int *offset)
|
||||
{
|
||||
|
@ -435,4 +435,74 @@ static inline void cec_phys_addr_invalidate(struct cec_adapter *adap)
|
||||
cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* cec_get_edid_spa_location() - find location of the Source Physical Address
|
||||
*
|
||||
* @edid: the EDID
|
||||
* @size: the size of the EDID
|
||||
*
|
||||
* This EDID is expected to be a CEA-861 compliant, which means that there are
|
||||
* at least two blocks and one or more of the extensions blocks are CEA-861
|
||||
* blocks.
|
||||
*
|
||||
* The returned location is guaranteed to be <= size-2.
|
||||
*
|
||||
* This is an inline function since it is used by both CEC and V4L2.
|
||||
* Ideally this would go in a module shared by both, but it is overkill to do
|
||||
* that for just a single function.
|
||||
*/
|
||||
static inline unsigned int cec_get_edid_spa_location(const u8 *edid,
|
||||
unsigned int size)
|
||||
{
|
||||
unsigned int blocks = size / 128;
|
||||
unsigned int block;
|
||||
u8 d;
|
||||
|
||||
/* Sanity check: at least 2 blocks and a multiple of the block size */
|
||||
if (blocks < 2 || size % 128)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If there are fewer extension blocks than the size, then update
|
||||
* 'blocks'. It is allowed to have more extension blocks than the size,
|
||||
* since some hardware can only read e.g. 256 bytes of the EDID, even
|
||||
* though more blocks are present. The first CEA-861 extension block
|
||||
* should normally be in block 1 anyway.
|
||||
*/
|
||||
if (edid[0x7e] + 1 < blocks)
|
||||
blocks = edid[0x7e] + 1;
|
||||
|
||||
for (block = 1; block < blocks; block++) {
|
||||
unsigned int offset = block * 128;
|
||||
|
||||
/* Skip any non-CEA-861 extension blocks */
|
||||
if (edid[offset] != 0x02 || edid[offset + 1] != 0x03)
|
||||
continue;
|
||||
|
||||
/* search Vendor Specific Data Block (tag 3) */
|
||||
d = edid[offset + 2] & 0x7f;
|
||||
/* Check if there are Data Blocks */
|
||||
if (d <= 4)
|
||||
continue;
|
||||
if (d > 4) {
|
||||
unsigned int i = offset + 4;
|
||||
unsigned int end = offset + d;
|
||||
|
||||
/* Note: 'end' is always < 'size' */
|
||||
do {
|
||||
u8 tag = edid[i] >> 5;
|
||||
u8 len = edid[i] & 0x1f;
|
||||
|
||||
if (tag == 3 && len >= 5 && i + len <= end &&
|
||||
edid[i + 1] == 0x03 &&
|
||||
edid[i + 2] == 0x0c &&
|
||||
edid[i + 3] == 0x00)
|
||||
return i + 4;
|
||||
i += len + 1;
|
||||
} while (i < end);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _MEDIA_CEC_H */
|
||||
|
Loading…
Reference in New Issue
Block a user